summaryrefslogtreecommitdiff
path: root/testapp
diff options
context:
space:
mode:
Diffstat (limited to 'testapp')
-rw-r--r--testapp/exam/forms.py29
-rw-r--r--testapp/exam/models.py62
-rw-r--r--testapp/exam/tests.py25
-rw-r--r--testapp/exam/views.py15
-rw-r--r--testapp/templates/exam/edit_quiz.html5
5 files changed, 113 insertions, 23 deletions
diff --git a/testapp/exam/forms.py b/testapp/exam/forms.py
index 7c66944..c96ac7e 100644
--- a/testapp/exam/forms.py
+++ b/testapp/exam/forms.py
@@ -12,7 +12,7 @@ from taggit_autocomplete_modified import settings
from string import letters, punctuation, digits
import datetime
-LANGUAGES = (
+languages = (
("select", "Select"),
("python", "Python"),
("bash", "Bash"),
@@ -22,7 +22,7 @@ LANGUAGES = (
("scilab", "Scilab"),
)
-QUESTION_TYPES = (
+question_types = (
("select", "Select"),
("mcq", "Multiple Choice"),
("code", "Code"),
@@ -31,7 +31,6 @@ QUESTION_TYPES = (
UNAME_CHARS = letters + "._" + digits
PWD_CHARS = letters + punctuation + digits
-
class UserRegisterForm(forms.Form):
"""A Class to create new form for User's Registration.
It has the various fields and functions required to register
@@ -127,23 +126,39 @@ class QuizForm(forms.Form):
"""Creates a form to add or edit a Quiz.
It has the related fields and functions required."""
+ def __init__(self, *args, **kwargs):
+ super(QuizForm, self).__init__(*args, **kwargs)
+ quizzes = [('', 'Select a prerequisite quiz')]
+ quizzes = quizzes + \
+ list(Quiz.objects.values_list('id','description'))
+ self.fields['prerequisite'] = forms.CharField(required=False,
+ widget=forms.Select(choices=quizzes))
+
start_date = forms.DateField(initial=datetime.date.today)
- duration = forms.IntegerField()
+ duration = forms.IntegerField(help_text='Will be taken in minutes')
active = forms.BooleanField(required=False)
description = forms.CharField(max_length=256, widget=forms.Textarea\
(attrs={'cols': 20, 'rows': 1}))
+ pass_criteria = forms.FloatField(initial=40,
+ help_text='Will be taken as percentage')
+ language = forms.CharField(widget=forms.Select(choices=languages))
def save(self):
start_date = self.cleaned_data["start_date"]
duration = self.cleaned_data["duration"]
active = self.cleaned_data['active']
description = self.cleaned_data["description"]
-
+ pass_criteria = self.cleaned_data["pass_criteria"]
+ language = self.cleaned_data["language"]
+ prerequisite = self.cleaned_data["prerequisite"]
new_quiz = Quiz()
new_quiz.start_date = start_date
new_quiz.duration = duration
new_quiz.active = active
new_quiz.description = description
+ new_quiz.pass_criteria = pass_criteria
+ new_quiz.language = language
+ new_quiz.prerequisite_id = prerequisite
new_quiz.save()
@@ -161,9 +176,9 @@ class QuestionForm(forms.Form):
options = forms.CharField(widget=forms.Textarea\
(attrs={'cols': 40, 'rows': 1}), required=False)
language = forms.CharField(max_length=20, widget=forms.Select\
- (choices=LANGUAGES))
+ (choices=languages))
type = forms.CharField(max_length=8, widget=forms.Select\
- (choices=QUESTION_TYPES))
+ (choices=question_types))
active = forms.BooleanField(required=False)
tags = TagField(widget=TagAutocomplete(), required=False)
snippet = forms.CharField(widget=forms.Textarea\
diff --git a/testapp/exam/models.py b/testapp/exam/models.py
index 42c5d5a..27d2987 100644
--- a/testapp/exam/models.py
+++ b/testapp/exam/models.py
@@ -16,7 +16,7 @@ class Profile(models.Model):
position = models.CharField(max_length=64)
-LANGUAGES = (
+languages = (
("python", "Python"),
("bash", "Bash"),
("C", "C Language"),
@@ -26,7 +26,7 @@ LANGUAGES = (
)
-QUESTION_TYPES = (
+question_types = (
("mcq", "Multiple Choice"),
("code", "Code"),
)
@@ -53,10 +53,10 @@ class Question(models.Model):
# The language for question.
language = models.CharField(max_length=24,
- choices=LANGUAGES)
+ choices=languages)
# The type of question.
- type = models.CharField(max_length=24, choices=QUESTION_TYPES)
+ type = models.CharField(max_length=24, choices=question_types)
# Is this question active or not. If it is inactive it will not be used
# when creating a QuestionPaper.
@@ -115,6 +115,15 @@ class Quiz(models.Model):
# Description of quiz.
description = models.CharField(max_length=256)
+ # Mininum passing percentage condition.
+ pass_criteria = models.FloatField("Passing percentage", default=40)
+
+ # List of prerequisite quizzes to be passed to take this quiz
+ prerequisite = models.ForeignKey("Quiz", null=True)
+
+ # Programming language for a quiz
+ language = models.CharField(max_length=20, choices=languages)
+
class Meta:
verbose_name_plural = "Quizzes"
@@ -137,11 +146,14 @@ class QuestionPaper(models.Model):
# Questions that will be fetched randomly from the Question Set.
random_questions = models.ManyToManyField("QuestionSet")
+ # Option to shuffle questions, each time a new question paper is created.
+ shuffle_questions = models.BooleanField(default=False)
+
# Total marks for the question paper.
total_marks = models.FloatField()
def update_total_marks(self):
- """ Returns the total marks for the Question Paper"""
+ """ Updates the total marks for the Question Paper"""
marks = 0.0
questions = self.fixed_questions.all()
for question in questions:
@@ -149,7 +161,6 @@ class QuestionPaper(models.Model):
for question_set in self.random_questions.all():
marks += question_set.marks * question_set.num_questions
self.total_marks = marks
- return None
def _get_questions_for_answerpaper(self):
""" Returns fixed and random questions for the answer paper"""
@@ -167,8 +178,9 @@ class QuestionPaper(models.Model):
+ datetime.timedelta(minutes=self.quiz.duration)
ans_paper.question_paper = self
questions = self._get_questions_for_answerpaper()
- question_ids = [str(x.id) for x in questions]
- shuffle(questions)
+ question_ids = [str(x.id) for x in questions]
+ if self.shuffle_questions:
+ shuffle(question_ids)
ans_paper.questions = "|".join(question_ids)
ans_paper.save()
return ans_paper
@@ -230,6 +242,15 @@ class AnswerPaper(models.Model):
# Teacher comments on the question paper.
comments = models.TextField()
+ # Total marks earned by the student in this paper.
+ marks_obtained = models.FloatField(null=True, default=None)
+
+ # Marks percent scored by the user
+ percent = models.FloatField(null=True, default=None)
+
+ # Result of the quiz, True if student passes the exam.
+ passed = models.NullBooleanField()
+
def current_question(self):
"""Returns the current active question to display."""
qs = self.questions.split('|')
@@ -298,9 +319,28 @@ class AnswerPaper(models.Model):
answered = ', '.join(sorted(qa))
return answered if answered else 'None'
- def get_marks_obtained(self):
- """Returns the total marks earned by student for this paper."""
- return sum([x.marks for x in self.answers.filter(marks__gt=0.0)])
+ def update_marks_obtained(self):
+ """Updates the total marks earned by student for this paper."""
+ marks = sum([x.marks for x in self.answers.filter(marks__gt=0.0)])
+ self.marks_obtained = marks
+
+ def update_percent(self):
+ """Updates the percent gained by the student for this paper."""
+ total_marks = self.question_paper.total_marks
+ if self.marks_obtained is not None:
+ percent = self.marks_obtained/self.question_paper.total_marks*100
+ self.percent = round(percent, 2)
+
+ def update_passed(self):
+ """
+ Checks whether student passed or failed, as per the quiz
+ passing criteria.
+ """
+ if self.percent is not None:
+ if self.percent >= self.question_paper.quiz.pass_criteria:
+ self.passed = True
+ else:
+ self.passed = False
def get_question_answers(self):
"""
diff --git a/testapp/exam/tests.py b/testapp/exam/tests.py
index b2ba36f..d76e4f8 100644
--- a/testapp/exam/tests.py
+++ b/testapp/exam/tests.py
@@ -21,7 +21,8 @@ def setUpModule():
# create a quiz
Quiz.objects.create(start_date='2014-06-16', duration=30, active=False,
- description='demo quiz')
+ description='demo quiz', pass_criteria=40,
+ language='Python', prerequisite=None)
def tearDownModule():
@@ -86,6 +87,9 @@ class QuizTestCases(unittest.TestCase):
self.assertEqual(self.quiz.duration, 30)
self.assertTrue(self.quiz.active is False)
self.assertEqual(self.quiz.description, 'demo quiz')
+ self.assertEqual(self.quiz.language, 'Python')
+ self.assertEqual(self.quiz.pass_criteria, 40)
+ self.assertEqual(self.quiz.prerequisite, None)
###############################################################################
@@ -98,7 +102,8 @@ class QuestionPaperTestCases(unittest.TestCase):
# create question paper
self.question_paper = QuestionPaper.objects.create(quiz=self.quiz,
- total_marks=0.0)
+ total_marks=0.0, shuffle_questions=True)
+
# add fixed set of questions to the question paper
self.question_paper.fixed_questions.add(self.questions[3],
self.questions[5])
@@ -135,6 +140,7 @@ class QuestionPaperTestCases(unittest.TestCase):
self.assertEqual(self.question_paper.quiz.description, 'demo quiz')
self.assertEqual(list(self.question_paper.fixed_questions.all()),
[self.questions[3], self.questions[5]])
+ self.assertTrue(self.question_paper.shuffle_questions)
def test_update_total_marks(self):
""" Test update_total_marks() method of Question Paper"""
@@ -257,9 +263,20 @@ class AnswerPaperTestCases(unittest.TestCase):
answered_question = self.answerpaper.get_answered_str()
self.assertEqual(answered_question, '1')
- def test_get_marks_obtained(self):
+ def test_update_marks_obtained(self):
""" Test get_marks_obtained() method of Answer Paper"""
- self.assertEqual(self.answerpaper.get_marks_obtained(), 1.0)
+ self.answerpaper.update_marks_obtained()
+ self.assertEqual(self.answerpaper.marks_obtained, 1.0)
+
+ def test_update_percent(self):
+ """ Test update_percent() method of Answerpaper"""
+ self.answerpaper.update_percent()
+ self.assertEqual(self.answerpaper.percent, 33.33)
+
+ def test_update_passed(self):
+ """ Test update_passed method of AnswerPaper"""
+ self.answerpaper.update_passed()
+ self.assertFalse(self.answerpaper.passed)
def test_get_question_answer(self):
""" Test get_question_answer() method of Answer Paper"""
diff --git a/testapp/exam/views.py b/testapp/exam/views.py
index 7353d82..422e16f 100644
--- a/testapp/exam/views.py
+++ b/testapp/exam/views.py
@@ -188,6 +188,9 @@ def edit_quiz(request):
duration = request.POST.getlist('duration')
active = request.POST.getlist('active')
description = request.POST.getlist('description')
+ pass_criteria = request.POST.getlist('pass_criteria')
+ language = request.POST.getlist('language')
+ prerequisite = request.POST.getlist('prerequisite')
for j, quiz_id in enumerate(quiz_list):
quiz = Quiz.objects.get(id=quiz_id)
@@ -195,6 +198,9 @@ def edit_quiz(request):
quiz.duration = duration[j]
quiz.active = active[j]
quiz.description = description[j]
+ quiz.pass_criteria = pass_criteria[j]
+ quiz.language = language[j]
+ quiz.prerequisite_id = prerequisite[j]
quiz.save()
return my_redirect("/exam/manage/showquiz/")
@@ -322,6 +328,9 @@ def add_quiz(request, quiz_id=None):
d.duration = form['duration'].data
d.active = form['active'].data
d.description = form['description'].data
+ d.pass_criteria = form['pass_criteria'].data
+ d.language = form['language'].data
+ d.prerequisite_id = form['prerequisite'].data
d.save()
quiz = Quiz.objects.get(id=quiz_id)
return my_redirect("/exam/manage/showquiz")
@@ -342,6 +351,9 @@ def add_quiz(request, quiz_id=None):
form.initial['duration'] = d.duration
form.initial['description'] = d.description
form.initial['active'] = d.active
+ form.initial['pass_criteria'] = d.pass_criteria
+ form.initial['language'] = d.language
+ form.initial['prerequisite'] = d.prerequisite_id
return my_render_to_response('exam/add_quiz.html',
{'form': form},
context_instance=ci)
@@ -910,6 +922,9 @@ def show_all_quiz(request):
form.initial['duration'] = d.duration
form.initial['active'] = d.active
form.initial['description'] = d.description
+ form.initial['pass_criteria'] = d.pass_criteria
+ form.initial['language'] = d.language
+ form.initial['prerequisite'] = d.prerequisite_id
forms.append(form)
return my_render_to_response('exam/edit_quiz.html',
{'forms': forms, 'data': data},
diff --git a/testapp/templates/exam/edit_quiz.html b/testapp/templates/exam/edit_quiz.html
index cf80df1..6445907 100644
--- a/testapp/templates/exam/edit_quiz.html
+++ b/testapp/templates/exam/edit_quiz.html
@@ -20,9 +20,12 @@
<table class=span1>
{% for form in forms %}
<tr><td><b>Start Date: <td>{{ form.start_date}}
- <tr><td><b>Duration: <td> {{ form.duration }}
+ <tr><td><b>Duration: <td> {{ form.duration }}<br>{{form.duration.help_text}}
<tr><td><b>Active: <td> {{ form.active }}
<tr><td><b>Description: <td> {{ form.description }}
+ <tr><td><b>Passing Criteria: <td> {{ form.pass_criteria }}<br>{{form.pass_criteria.help_text}}
+ <tr><td><b>Language: <td> {{ form.language }}
+ <tr><td><b>Prerequisite: <td> {{ form.prerequisite }}
<hr>
{% endfor %}
</table>