summaryrefslogtreecommitdiff
path: root/yaksh/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh/models.py')
-rw-r--r--yaksh/models.py189
1 files changed, 113 insertions, 76 deletions
diff --git a/yaksh/models.py b/yaksh/models.py
index 6e59d7a..32fb0d0 100644
--- a/yaksh/models.py
+++ b/yaksh/models.py
@@ -5,24 +5,11 @@ from itertools import islice, cycle
from collections import Counter
from django.db import models
from django.contrib.auth.models import User
+from django.forms.models import model_to_dict
+from django.contrib.contenttypes.models import ContentType
from taggit.managers import TaggableManager
-###############################################################################
-class ConcurrentUser(models.Model):
- concurrent_user = models.OneToOneField(User, null=False)
- session_key = models.CharField(null=False, max_length=40)
-
-
-###############################################################################
-class Profile(models.Model):
- """Profile for a user to store roll number and other details."""
- user = models.OneToOneField(User)
- roll_number = models.CharField(max_length=20)
- institute = models.CharField(max_length=128)
- department = models.CharField(max_length=64)
- position = models.CharField(max_length=64)
-
languages = (
("python", "Python"),
("bash", "Bash"),
@@ -45,6 +32,12 @@ enrollment_methods = (
("open", "Open Course"),
)
+test_case_types = (
+ ("standardtestcase", "Standard Testcase"),
+ ("stdoutbasedtestcase", "Stdout Based Testcase"),
+ ("mcqtestcase", "MCQ Testcase"),
+ )
+
attempts = [(i, i) for i in range(1, 6)]
attempts.append((-1, 'Infinite'))
days_between_attempts = ((j, j) for j in range(401))
@@ -54,10 +47,15 @@ test_status = (
('completed', 'Completed'),
)
-
def get_assignment_dir(instance, filename):
return '%s/%s' % (instance.user.roll_number, instance.assignmentQuestion.id)
+def get_model_class(model):
+ ctype = ContentType.objects.get(app_label="yaksh", model=model)
+ model_class = ctype.model_class()
+
+ return model_class
+
###############################################################################
class Course(models.Model):
@@ -132,6 +130,21 @@ class Course(models.Model):
def __unicode__(self):
return self.name
+###############################################################################
+class ConcurrentUser(models.Model):
+ concurrent_user = models.OneToOneField(User, null=False)
+ session_key = models.CharField(null=False, max_length=40)
+
+
+###############################################################################
+class Profile(models.Model):
+ """Profile for a user to store roll number and other details."""
+ user = models.OneToOneField(User)
+ roll_number = models.CharField(max_length=20)
+ institute = models.CharField(max_length=128)
+ department = models.CharField(max_length=64)
+ position = models.CharField(max_length=64)
+
###############################################################################
class Question(models.Model):
@@ -146,16 +159,6 @@ class Question(models.Model):
# Number of points for the question.
points = models.FloatField(default=1.0)
- # Answer for MCQs.
- test = models.TextField(blank=True)
-
- # Test cases file paths (comma seperated for reference code path and test case code path)
- # Applicable for CPP, C, Java and Scilab
- ref_code_path = models.TextField(blank=True)
-
- # Any multiple choice options. Place one option per line.
- options = models.TextField(blank=True)
-
# The language for question.
language = models.CharField(max_length=24,
choices=languages)
@@ -163,64 +166,49 @@ class Question(models.Model):
# The type of question.
type = models.CharField(max_length=24, choices=question_types)
+ # The type of evaluator
+ test_case_type = models.CharField(max_length=24, choices=test_case_types)
+
# Is this question active or not. If it is inactive it will not be used
# when creating a QuestionPaper.
active = models.BooleanField(default=True)
- # Snippet of code provided to the user.
- snippet = models.CharField(max_length=256, blank=True)
-
# Tags for the Question.
tags = TaggableManager(blank=True)
+ # Snippet of code provided to the user.
+ snippet = models.CharField(max_length=256, blank=True)
+
# user for particular question
user = models.ForeignKey(User, related_name="user")
- def consolidate_answer_data(self, test_cases, user_answer):
- test_case_data_dict = []
- question_info_dict = {}
-
- for test_case in test_cases:
- kw_args_dict = {}
- pos_args_list = []
-
- test_case_data = {}
- test_case_data['test_id'] = test_case.id
- test_case_data['func_name'] = test_case.func_name
- test_case_data['expected_answer'] = test_case.expected_answer
-
- if test_case.kw_args:
- for args in test_case.kw_args.split(","):
- arg_name, arg_value = args.split("=")
- kw_args_dict[arg_name.strip()] = arg_value.strip()
+ def consolidate_answer_data(self, user_answer):
+ question_data = {}
+ test_case_data = []
- if test_case.pos_args:
- for args in test_case.pos_args.split(","):
- pos_args_list.append(args.strip())
+ test_cases = self.get_test_cases()
- test_case_data['kw_args'] = kw_args_dict
- test_case_data['pos_args'] = pos_args_list
- test_case_data_dict.append(test_case_data)
+ for test in test_cases:
+ test_case_as_dict = test.get_field_value()
+ test_case_data.append(test_case_as_dict)
- # question_info_dict['language'] = self.language
- question_info_dict['id'] = self.id
- question_info_dict['user_answer'] = user_answer
- question_info_dict['test_parameter'] = test_case_data_dict
- question_info_dict['ref_code_path'] = self.ref_code_path
- question_info_dict['test'] = self.test
+ question_data['test_case_data'] = test_case_data
+ question_data['user_answer'] = user_answer
- return json.dumps(question_info_dict)
+ return json.dumps(question_data)
def dump_into_json(self, question_ids, user):
questions = Question.objects.filter(id__in = question_ids, user_id = user.id)
questions_dict = []
for question in questions:
- q_dict = {'summary': question.summary, 'description': question.description,
- 'points': question.points, 'test': question.test,
- 'ref_code_path': question.ref_code_path,
- 'options': question.options, 'language': question.language,
- 'type': question.type, 'active': question.active,
- 'snippet': question.snippet}
+ q_dict = {'summary': question.summary,
+ 'description': question.description,
+ 'points': question.points,
+ 'language': question.language,
+ 'type': question.type,
+ 'active': question.active,
+ 'test_case_type': question.test_case_type,
+ 'snippet': question.snippet}
questions_dict.append(q_dict)
return json.dumps(questions_dict, indent=2)
@@ -231,6 +219,28 @@ class Question(models.Model):
question['user'] = user
Question.objects.get_or_create(**question)
+ def get_test_cases(self, **kwargs):
+ test_case_ctype = ContentType.objects.get(app_label="yaksh",
+ model=self.test_case_type
+ )
+ test_cases = test_case_ctype.get_all_objects_for_this_type(
+ question=self,
+ **kwargs
+ )
+
+ return test_cases
+
+ def get_test_case(self, **kwargs):
+ test_case_ctype = ContentType.objects.get(app_label="yaksh",
+ model=self.test_case_type
+ )
+ test_case = test_case_ctype.get_object_for_this_type(
+ question=self,
+ **kwargs
+ )
+
+ return test_case
+
def __unicode__(self):
return self.summary
@@ -371,10 +381,13 @@ class QuestionPaper(models.Model):
def make_answerpaper(self, user, ip, attempt_num):
"""Creates an answer paper for the user to attempt the quiz"""
- ans_paper = AnswerPaper(user=user, user_ip=ip, attempt_number=attempt_num)
+ ans_paper = AnswerPaper(user=user,
+ user_ip=ip,
+ attempt_number=attempt_num
+ )
ans_paper.start_time = datetime.now()
- ans_paper.end_time = ans_paper.start_time \
- + timedelta(minutes=self.quiz.duration)
+ ans_paper.end_time = ans_paper.start_time + \
+ timedelta(minutes=self.quiz.duration)
ans_paper.question_paper = self
ans_paper.save()
questions = self._get_questions_for_answerpaper()
@@ -746,14 +759,38 @@ class AssignmentUpload(models.Model):
class TestCase(models.Model):
question = models.ForeignKey(Question, blank=True, null = True)
- # Test case function name
- func_name = models.CharField(blank=True, null = True, max_length=200)
+class StandardTestCase(TestCase):
+ test_case = models.TextField(blank=True)
+
+ def get_field_value(self):
+ return {"test_case": self.test_case}
+
+ def __unicode__(self):
+ return u'Question: {0} | Test Case: {1}'.format(self.question,
+ self.test_case
+ )
+
- # Test case Keyword arguments in dict form
- kw_args = models.TextField(blank=True, null = True)
+class StdoutBasedTestCase(TestCase):
+ expected_output = models.TextField(blank=True)
- # Test case Positional arguments in list form
- pos_args = models.TextField(blank=True, null = True)
+ def get_field_value(self):
+ return {"expected_output": self.expected_output}
- # Test case Expected answer in list form
- expected_answer = models.TextField(blank=True, null = True)
+ def __unicode__(self):
+ return u'Question: {0} | Exp. Output: {1}'.format(self.question,
+ self.expected_output
+ )
+
+
+class McqTestCase(TestCase):
+ options = models.TextField()
+ correct = models.BooleanField(default=False)
+
+ def get_field_value(self):
+ return {"options": self.options, "correct": self.correct}
+
+ def __unicode__(self):
+ return u'Question: {0} | Correct: {1}'.format(self.question,
+ self.correct
+ )