summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--yaksh/forms.py102
-rw-r--r--yaksh/models.py24
-rw-r--r--yaksh/templates/yaksh/automatic_questionpaper.html87
-rw-r--r--yaksh/templates/yaksh/edit_question.html61
-rw-r--r--yaksh/templates/yaksh/edit_quiz.html39
-rw-r--r--yaksh/templates/yaksh/editquestionpaper.html15
-rw-r--r--yaksh/templates/yaksh/manual_questionpaper.html79
-rw-r--r--yaksh/templates/yaksh/question.html18
-rw-r--r--yaksh/templates/yaksh/quizlist.html24
-rw-r--r--yaksh/templates/yaksh/quizzes_user.html4
-rw-r--r--yaksh/templates/yaksh/show_quiz.html33
-rw-r--r--yaksh/templates/yaksh/showquestions.html1
-rw-r--r--yaksh/tests.py15
-rw-r--r--yaksh/urls.py11
-rw-r--r--yaksh/views.py688
15 files changed, 222 insertions, 979 deletions
diff --git a/yaksh/forms.py b/yaksh/forms.py
index 1af02f7..6ad388f 100644
--- a/yaksh/forms.py
+++ b/yaksh/forms.py
@@ -127,119 +127,27 @@ class UserLoginForm(forms.Form):
return user
-class QuizForm(forms.Form):
+class QuizForm(forms.ModelForm):
"""Creates a form to add or edit a Quiz.
It has the related fields and functions required."""
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(QuizForm, self).__init__(*args, **kwargs)
- quizzes = [('', 'Select a prerequisite quiz')]
- quizzes += list(Quiz.objects.filter(
- course__creator=user).values_list('id', 'description'))
- self.fields['prerequisite'] = forms.CharField(required=False,
- widget=forms.Select(choices=quizzes))
+ self.fields['prerequisite'] = forms.ModelChoiceField(
+ queryset=Quiz.objects.filter(course__creator=user))
self.fields['course'] = forms.ModelChoiceField(
queryset=Course.objects.filter(creator=user))
- start_date = forms.DateField(initial=datetime.date.today(), required=False)
- start_time = forms.TimeField(initial=datetime.datetime.now().time(), required=False)
- end_date = forms.DateField(initial=datetime.date(2199, 1, 1), required=False)
- end_time = forms.TimeField(initial=datetime.time(0, 0, 0, 0), required=False)
- 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))
- attempts_allowed = forms.IntegerField(widget=forms.Select(choices=attempts))
- time_between_attempts = forms.IntegerField\
- (widget=forms.Select(choices=days_between_attempts),
- help_text='Will be in days')
- def save(self):
- course = self.cleaned_data["course"]
- start_date = self.cleaned_data["start_date"]
- start_time = self.cleaned_data["start_time"]
- end_date = self.cleaned_data["end_date"]
- end_time = self.cleaned_data["end_time"]
- 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"]
- attempts_allowed = self.cleaned_data["attempts_allowed"]
- time_between_attempts = self.cleaned_data["time_between_attempts"]
- new_quiz = Quiz()
- new_quiz.course = course
- new_quiz.start_date_time = datetime.datetime.combine(start_date,
- start_time)
- new_quiz.end_date_time = datetime.datetime.combine(end_date,
- end_time)
- 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.attempts_allowed = attempts_allowed
- new_quiz.time_between_attempts = time_between_attempts
- new_quiz.save()
+ class Meta:
+ model = Quiz
class QuestionForm(forms.ModelForm):
"""Creates a form to add or edit a Question.
It has the related fields and functions required."""
- summary = forms.CharField(widget=forms.Textarea\
- (attrs={'cols': 40, 'rows': 1}))
- description = forms.CharField(widget=forms.Textarea\
- (attrs={'cols': 40, 'rows': 1}))
- points = forms.FloatField()
- test = forms.CharField(widget=forms.Textarea\
- (attrs={'cols': 40, 'rows': 1}), required=False)
- options = forms.CharField(widget=forms.Textarea\
- (attrs={'cols': 40, 'rows': 1}), required=False)
- language = forms.CharField(max_length=20, widget=forms.Select\
- (choices=languages))
- type = forms.CharField(max_length=8, widget=forms.Select\
- (choices=question_types))
- active = forms.BooleanField(required=False)
- tags = TagField(required=False)
- snippet = forms.CharField(widget=forms.Textarea\
- (attrs={'cols': 40, 'rows': 1}), required=False)
- ref_code_path = forms.CharField(widget=forms.Textarea\
- (attrs={'cols': 40, 'rows': 1}), required=False)
-
- def save(self, commit=True):
- summary = self.cleaned_data.get("summary")
- description = self.cleaned_data.get("description")
- points = self.cleaned_data.get("points")
- test = self.cleaned_data.get("test")
- options = self.cleaned_data.get("options")
- language = self.cleaned_data.get("language")
- type = self.cleaned_data.get("type")
- active = self.cleaned_data.get("active")
- snippet = self.cleaned_data.get("snippet")
-
- new_question = Question()
- new_question.summary = summary
- new_question.description = description
- new_question.points = points
- new_question.test = test
- new_question.options = options
- new_question.language = language
- new_question.type = type
- new_question.active = active
- new_question.snippet = snippet
- new_question = super(QuestionForm, self).save(commit=False)
- if commit:
- new_question.save()
-
- return new_question
-
class Meta:
model = Question
diff --git a/yaksh/models.py b/yaksh/models.py
index 30257ef..856698f 100644
--- a/yaksh/models.py
+++ b/yaksh/models.py
@@ -155,10 +155,10 @@ class Question(models.Model):
active = models.BooleanField(default=True)
# Snippet of code provided to the user.
- snippet = models.CharField(max_length=256)
+ snippet = models.CharField(max_length=256, blank=True)
# Tags for the Question.
- tags = TaggableManager()
+ tags = TaggableManager(blank=True)
def consolidate_answer_data(self, test_cases, user_answer):
test_case_data_dict = []
@@ -262,7 +262,7 @@ class Quiz(models.Model):
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)
+ prerequisite = models.ForeignKey("Quiz", null=True, blank=True)
# Programming language for a quiz
language = models.CharField(max_length=20, choices=languages)
@@ -341,17 +341,17 @@ class QuestionPaper(models.Model):
ans_paper.questions_unanswered.add(*questions)
return ans_paper
- def is_questionpaper_passed(self, user):
+ def _is_questionpaper_passed(self, user):
return AnswerPaper.objects.filter(question_paper=self, user=user,
passed = True).exists()
- def is_attempt_allowed(self, user):
+ def _is_attempt_allowed(self, user):
attempts = AnswerPaper.objects.get_total_attempt(questionpaper=self,
user=user)
return attempts != self.quiz.attempts_allowed
def can_attempt_now(self, user):
- if self.is_attempt_allowed(user):
+ if self._is_attempt_allowed(user):
last_attempt = AnswerPaper.objects.get_user_last_attempt(user=user,
questionpaper=self)
if last_attempt:
@@ -362,6 +362,15 @@ class QuestionPaper(models.Model):
else:
return False
+ def _get_prequisite_paper(self):
+ return self.quiz.prerequisite.questionpaper_set.get()
+
+ def is_prerequisite_passed(self, user):
+ if self.quiz.has_prerequisite():
+ prerequisite = self._get_prequisite_paper()
+ return prerequisite._is_questionpaper_passed(user)
+
+
###############################################################################
class QuestionSet(models.Model):
"""Question set contains a set of questions from which random questions
@@ -642,6 +651,9 @@ class AnswerPaper(models.Model):
if self.status == 'inprogress':
return self.time_left()> 0
+ def get_previous_answers(self, question):
+ if question.type == 'code':
+ return self.answers.filter(question=question).order_by('-id')
def __unicode__(self):
u = self.user
diff --git a/yaksh/templates/yaksh/automatic_questionpaper.html b/yaksh/templates/yaksh/automatic_questionpaper.html
deleted file mode 100644
index b9a4ae0..0000000
--- a/yaksh/templates/yaksh/automatic_questionpaper.html
+++ /dev/null
@@ -1,87 +0,0 @@
-{% extends "manage.html" %}
-
-
-{% block subtitle %}Design Question Paper{% endblock %}
-
-{% block css %}
-<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/question_quiz.css" type="text/css" />
-<link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/autotaggit.css" />
-<style>
-select
-{
- width:auto;
-}
-</style>
-{% endblock %}
-{% block script %}
-<script src="/static/yaksh/js/jquery-1.4.2.min.js" type="text/javascript"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/add_questionpaper.js"></script>
-{% endblock %}
-
-{% block manage %}
-<input type=hidden id="url_root" value={{ URL_ROOT }}>
-<center><b>Automatic mode to design the Question Paper</center><br>
-<form action="" method="post" name=frm>
- {% csrf_token %}
- <center>
- Tag Conditions:
- <select name='first_tag'>
- <option value="">Select Tag </option>
- {% for tag in data.tags %}
- <option value={{tag}}>{{tag}}</option>
- {% endfor %}
- </select>
-
- <select name='first_condition'>
- <option value="or">OR</option>
- <option value="and">AND</option>
- </select>
-
- <select name='second_tag'>
- <option value="">Select Tag </option>
- {% for tag in data.tags %}
- <option value={{tag}}>{{tag}}</option>
- {% endfor %}
- </select>
-
- <select name='second_condition'>
- <option value="or">OR</option>
- <option value="and">AND</option>
- </select>
-
- <select name='third_tag'>
- <option value="null">Select Tag </option>
- {% for tag in data.tags %}
- <option value={{tag}}>{{tag}}</option>
- {% endfor %}
- </select>
- </center>
-
- <br>
-
- <center>Number of question: <input type=text id=num_questions name='num_questions' style="width:25px;">&nbsp;<button class=btn type=submit name='fetch' value='fetch'>Fetch Questions</button><br></center>
-
- <br>
- <br>
- <p><b>Below is the list of Questions fetched according to the given tag conditions</p>
- <hr>
- <center><table class=span10>
- <th>Summary
- <th>Type
- <th>Points
- <th>Tags
- {% for question in data.questions %}
- <input type=hidden name='questions' value={{ question.id }} />
- <tr><td>{{ question.summary }} <td>{{ question.type }} <td>{{ question.points }} <td>
- {% for tag in question.tags.all %}
- {{ tag }}
- {% endfor %}
- </tr>
- <br>
- {% endfor %}
- </table>
- {% if data.msg %}<div class="alert alert-error">{{ data.msg }}</div>{% endif %}
- <center><button class=btn type=submit name='save' value='save'>Save Question Paper</button></center>
-</form>
-
-{% endblock %}
diff --git a/yaksh/templates/yaksh/edit_question.html b/yaksh/templates/yaksh/edit_question.html
deleted file mode 100644
index 9a66250..0000000
--- a/yaksh/templates/yaksh/edit_question.html
+++ /dev/null
@@ -1,61 +0,0 @@
-{% extends "manage.html" %}
-
-{% block subtitle %}Edit Question{% endblock %}
-
-{% block css %}
-<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/question_quiz.css" type="text/css" />
-<link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/autotaggit.css" />
-{% endblock %}
-{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/edit_question.js"></script>
-<script src="/static/yaksh/js/jquery-1.4.2.min.js" type="text/javascript"></script>
-{% endblock %}
-
-{% block onload %} onload = 'javascript:textareaformat();' {% endblock %}
-
-{% block manage %}
-<form name='frm' action="{{URL_ROOT}}/exam/manage/editquestion/" method="post" onSubmit="return autosubmit()" onKeyPress='javascript:render_question(frm);'>
- {% csrf_token %}
-<center><p>Click on the Question links to edit the question.</p></center>
-
-<table>
-
- {% for question, test in data_list %}
-
- <tr><td height=10><a id='a{{forloop.counter}}' onClick="data('contentDiv{{forloop.counter}}','myContent{{forloop.counter}}','a{{forloop.counter}}','{{question.summary.value}}');" style='cursor:pointer;'>{{question.summary.value}}</a>
-
- <div id="contentDiv{{forloop.counter}}" style="display:none;">
- <div id="myContent{{forloop.counter}}" style="display: none;">
-
- <center><table class=span1>
- <tr><td><b>Summary:</b> <td>{{ question.summary }}{{ question.summary.errors }}
- <tr><td><b> Language: </b><td> {{question.language}}{{question.language.errors}}
- <tr><td><b> Active: </b><td>&nbsp; {{ question.active }}{{question.active.errors}} &nbsp; Type: &nbsp;{{ question.type }}{{question.type.errors}}
- <tr><td><b>Points:<td><button class="btn-mini" name={{forloop.counter}} type="button" onClick="increase(frm,{{forloop.counter}});">+</button>{{ question.points }}<button class="btn-mini" type="button" onClick="decrease(frm,{{forloop.counter}});">-</button>{{ question.points.errors }}
- <tr><td><strong>Rendered: </strong><td><p id='my{{forloop.counter}}'></p>
- <tr><td><b>Description: <td>{{ question.description }}
- {{question.description.errors}} <tr><td><b>Test: <td>
- {{ question.test }}{{question.test.errors}}
- <tr><td><b>Snippet: <td>{{ question.snippet }}{{ question.snippet.errors }}
- </td></b></td></tr>
- <tr><td><b>Tags: </b><td>{{ question.tags }}
- <tr><td id='label_option{{forloop.counter}}'><b>Options:<td>{{ question.options }}
- {{question.options.errors}} {{question.options.helptext}}
- </table></center>
- <center><table class=span1>
- {{ test }}
- </table></center>
- </div>
- </div>
- {% endfor %}
-</table></center>
-
-
-{% for i in data %}
- <input type=hidden name='questions' value="{{ i }}" />
-{% endfor %}
-
- <center><button class="btn" type="submit" name="savequestion">Save</button>
- <button class="btn" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/questions/");'>Cancel</button> </center>
-</form>
-{% endblock %}
diff --git a/yaksh/templates/yaksh/edit_quiz.html b/yaksh/templates/yaksh/edit_quiz.html
deleted file mode 100644
index fb7df93..0000000
--- a/yaksh/templates/yaksh/edit_quiz.html
+++ /dev/null
@@ -1,39 +0,0 @@
-{% extends "manage.html" %}
-
-
-{% block subtitle %}Edit Quiz(zes){% endblock %}
-
-{% block css %}
-<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/question_quiz.css" type="text/css" />
-{% endblock %}
-
-{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/edit_quiz.js"></script>
-{% endblock %}
-
-{% block onload %} onload = 'javascript:form_load();' {% endblock %}
-
-{% block manage %}
-<form name=frm action="{{URL_ROOT}}/exam/manage/editquiz/" method="post">
- {% csrf_token %}
- <center>
- <table class=span1>
- {% for form in forms %}
- <tr><td><b>Start Date: <td>{{ form.start_date}}
- <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>
- </center>
-{% for i in data %}
- <input type=hidden name='quizzes' value="{{ i }}" />
-{% endfor %}
- <center><button class="btn" type="submit" name="save">Save</button>
- <button class="btn" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/showquiz/");'>Cancel</button> </center>
-</form>
-{% endblock %}
diff --git a/yaksh/templates/yaksh/editquestionpaper.html b/yaksh/templates/yaksh/editquestionpaper.html
index 2b7b835..fa6d7d7 100644
--- a/yaksh/templates/yaksh/editquestionpaper.html
+++ b/yaksh/templates/yaksh/editquestionpaper.html
@@ -10,12 +10,17 @@
{% block manage %}
<form name=frm action="" method="post">
{% csrf_token %}
-
-{% for i in papers.questions %}
-<input type="checkbox" name="papers" value="{{ i.id }}">&nbsp;&nbsp;<a href="{{URL_ROOT}}/exam/manage/addquestion/{{ i.id }}">{{ i.summary}}</a><br>
+<p><u> Fixed Questions </u></p>
+{% for q in fixed_questions %}
+<input type="checkbox" name="papers" value="{{ q.id }}">&nbsp;&nbsp;<a href="{{URL_ROOT}}/exam/manage/addquestion/{{ q.id }}">{{ q.summary}}</a><br>
+{% endfor %}
+<p><u> Random Questions </u></p>
+{% for random_set in random_questions %}
+<p>{{ random_set.num_questions}} question(s) from {{ random_set.questions.all|length }} question(s)</p>
+{% for q in random_set.questions.all %}
+<input type="checkbox" name="papers" value="{{ q.id }}">&nbsp;&nbsp;<a href="{{URL_ROOT}}/exam/manage/addquestion/{{ q.id }}">{{ q.summary}}</a><br>
+{% endfor %}
{% endfor %}
<br>
-<button class="btn" type="submit" name='add' value=add>Add Question</button>&nbsp;&nbsp;
-<button class="btn" type="submit" onClick="return confirm_delete(frm);" name='delete' value='delete'>Delete Selected</button>
</form>
{% endblock %}
diff --git a/yaksh/templates/yaksh/manual_questionpaper.html b/yaksh/templates/yaksh/manual_questionpaper.html
deleted file mode 100644
index 86bfd67..0000000
--- a/yaksh/templates/yaksh/manual_questionpaper.html
+++ /dev/null
@@ -1,79 +0,0 @@
-{% extends "manage.html" %}
-
-
-{% block subtitle %}Design Question Paper{% endblock %}
-
-{% block css %}
-<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/question_quiz.css" type="text/css" />
-<link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/autotaggit.css" />
-<style>
-select
-{
- width:auto;
-}
-</style>
-{% endblock %}
-{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery-1.4.2.min.js" type="text/javascript"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/add_questionpaper.js"></script>
-{% endblock %}
-
-{% block manage %}
-<input type=hidden id="url_root" value={{ URL_ROOT }}>
-<center><b>Manual mode to design the Question Paper</center><br>
-
-<form action="" method="post" name=frm>
- {% csrf_token %}
- <center>
- Tag Conditions:
- <select name='first_tag'>
- <option value="">Select Tag </option>
- {% for tag in data.tags %}
- <option value={{tag}}>{{tag}}</option>
- {% endfor %}
- </select>
- <select name='first_condition'>
- <option value="or">OR</option>
- <option value="and">AND</option>
- </select>
- <select name='second_tag'>
- <option value="">Select Tag </option>
- {% for tag in data.tags %}
- <option value={{tag}}>{{tag}}</option>
- {% endfor %}
- </select>
- <select name='second_condition'>
- <option value="or">OR</option>
- <option value="and">AND</option>
- </select>
- <select name='third_tag'>
- <option value="null">Select Tag </option>
- {% for tag in data.tags %}
- <option value={{tag}}>{{tag}}</option>
- {% endfor %}
- </select>
- </center>
- <br>
- <center><button class=btn type=submit name='fetch' value='fetch'>Fetch Questions</button>
- <br><br><b>Below is the list of Questions fetched according to the given tag conditions</b></center>
- <hr>
- <center><table class=span10>
- <th> &nbsp;
- <th>Summary
- <th>Type
- <th>Points
- <th>Tags
- {% for question in data.questions %}
- <tr><td><input type=checkbox name=questions value={{question.id}}> <td> {{ question.summary }} <td>{{ question.type }} <td>{{ question.points }} <td>
- {% for tag in question.tags.all %}
- {{ tag }}
- {% endfor %}
- </tr>
- <br>
- {% endfor %}
- </table>
- {% if data.msg %}<div class="alert alert-error">{{ data.msg }}</div>{% endif %}
- <center><button class=btn type=submit name='save' value='save'>Save Question Paper</button></center>
-</form>
-
-{% endblock %}
diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html
index 0c48167..1fb70b8 100644
--- a/yaksh/templates/yaksh/question.html
+++ b/yaksh/templates/yaksh/question.html
@@ -90,19 +90,19 @@ function call_skip(url)
form.action = url
form.submit();
}
- {% if question.type == 'code' and success == 'True'%}
+ {% if error_message == 'Correct Output'%}
{% if paper.questions_left %}
window.setTimeout(function()
{
{% for qid in paper.questions.all %}
- location.href="{{ URL_ROOT }}/exam/{{ qid.id }}/{{ paper.attempt_number }}/{{ paper.question_paper.id }}/"
+ location.href="{{ URL_ROOT }}/exam/{{ qid.id }}/check/{{ paper.attempt_number }}/{{ paper.question_paper.id }}/"
{% endfor %}
- }, 1000);
+ }, 2000);
{% else %}
window.setTimeout(function()
{
location.href="{{ URL_ROOT }}/exam/{{ question.id }}/check/{{ paper.attempt_number }}/{{ paper.question_paper.id }}/"
- }, 1000);
+ }, 2000);
{% endif %}
{% endif %}
</script>
@@ -132,21 +132,19 @@ function call_skip(url)
{% for qid in paper.questions.all %}
{% if qid in paper.questions_unanswered.all %}
{% if qid.id == question.id %}
- {{ q.id}}
- <li class="active"><a href="#" data-toggle="tooltip" title="{{ qid.description }}" onclick="call_skip('{{ URL_ROOT }}/exam/{{ qid.id }}/{{ paper.attempt_number }}/{{ paper.question_paper.id }}/')">{{ forloop.counter }}</a></li>
+ <li class="active"><a href="#"data-toggle="tooltip" title="{{ qid.description }}" onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ qid.id }}/{{ paper.attempt_number }}/{{ paper.question_paper.id }}/')">{{ forloop.counter }}</a></li>
{% else %}
- <li><a href="#" data-toggle="tooltip" title="{{ qid.description }}" onclick="call_skip('{{ URL_ROOT }}/exam/{{ qid.id }}/{{ paper.attempt_number }}/{{ paper.question_paper.id }}/')">{{ forloop.counter }}</a></li>
+ <li><a href="#" data-toggle="tooltip" title="{{ qid.description }}" onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ qid.id }}/{{ paper.attempt_number }}/{{ paper.question_paper.id }}/')">{{ forloop.counter }}</a></li>
{% endif %}
{% endif %}
{% if qid in paper.questions_answered.all %}
- <li class="disabled"><a href="#">{{ forloop.counter }}</a></li>
+ <li class="disabled"><a href="#" data-toggle="tooltip" title="{{ qid.description }}" >{{ forloop.counter }}</a></li>
{% endif %}
{% endfor %}
</ul>
</div>
</div>
</div>
-
<div class="span13">
<h4><u> {{ question.summary }} </u><font class=pull-right>(Marks : {{ question.points }}) </font></h4><br>
<font size=3 face=arial> {{ question.description|safe }} </font>
@@ -204,7 +202,7 @@ function call_skip(url)
<button class="btn" type="submit" name="check" id="check" onClick="submitCode();">Check Answer</button>&nbsp;&nbsp;
{% endif %}
{% if paper.unanswered.all|length != 1 %}
- <button class="btn" type="submit" name="skip" id="skip">Attempt Later</button>
+ <button class="btn" onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ paper.attempt_number }}/{{ paper.question_paper.id }}/')" name="skip" id="skip">Attempt Later</button>
{% endif %}
</form>
</div>
diff --git a/yaksh/templates/yaksh/quizlist.html b/yaksh/templates/yaksh/quizlist.html
deleted file mode 100644
index 9b1fd73..0000000
--- a/yaksh/templates/yaksh/quizlist.html
+++ /dev/null
@@ -1,24 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %} Quiz List {% endblock title %}
-
-{% block formtitle %} Quiz List {% endblock %}
-
-{% block pagetitle %} Online Test {% endblock %}
-
-{% block content %}
-{% if not quizzes and not quiz %}
-<center><h5> No quizzes available. </h5></center>
-{% endif %}
-
-{% if quizzes %}
-<form method="post" action="" name='frm'>
-{% csrf_token %}
-
-{% for quiz in quizzes %}
-<a href="{{URL_ROOT}}/exam/start/{{quiz.id}}/">{{ quiz.description }}</a><br>
-{% endfor %}
-</form>
-{% endif %}
-
-{% endblock %}
diff --git a/yaksh/templates/yaksh/quizzes_user.html b/yaksh/templates/yaksh/quizzes_user.html
index 69cf3ba..223952e 100644
--- a/yaksh/templates/yaksh/quizzes_user.html
+++ b/yaksh/templates/yaksh/quizzes_user.html
@@ -54,11 +54,11 @@
<tr>
{% if not quiz.is_expired %}
<td>
- <a href="{{ URL_ROOT }}/exam/intro/{{quiz.questionpaper_set.get.id}}">{{ quiz.description }}</a><br>
+ <a href="{{ URL_ROOT }}/exam/start/{{quiz.questionpaper_set.get.id}}">{{ quiz.description }}</a><br>
</td>
{% else %}
<td>
- <a href="{{ URL_ROOT }}/exam/intro/{{quiz.questionpaper_set.get.id}}">{{ quiz.description }}</a><br>
+ <a href="{{ URL_ROOT }}/exam/start/{{quiz.questionpaper_set.get.id}}">{{ quiz.description }}</a><br>
{{ quiz.description }} <span class="label important">INACTIVE</span><br>
</td>
{% endif %}
diff --git a/yaksh/templates/yaksh/show_quiz.html b/yaksh/templates/yaksh/show_quiz.html
deleted file mode 100644
index 2cd4e11..0000000
--- a/yaksh/templates/yaksh/show_quiz.html
+++ /dev/null
@@ -1,33 +0,0 @@
-{% extends "manage.html" %}
-
-{% block title %} Quiz List {% endblock title %}
-
-{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/show_quiz.js"></script>
-{% endblock %}
-
-{% block subtitle %} Quiz List {% endblock %}
-{% block manage %}
-{% if not quizzes and not quiz %}
-<center><h5> No quizzes available. </h5></center>
-<button class="btn" type="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/addquiz");'>Add New Quiz</button>&nbsp;&nbsp;
-{% endif %}
-
-{# ############################################################### #}
-{# This is rendered when we are just viewing exam/monitor #}
-{% if quizzes %}
-<form method="post" action="" name='frm'>
-{% csrf_token %}
-
-{% for quiz in quizzes %}
-<input type=checkbox name='quiz' value={{quiz.id}} />&nbsp;&nbsp;<a href="{{URL_ROOT}}/exam/manage/addquiz/{{quiz.id}}/">{{ quiz.description }}</a><br>
-{% endfor %}
-
-<br><br>
-<button class="btn" type="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/addquiz");'>Add New Quiz</button>&nbsp;&nbsp;
-<button class="btn" type="submit" name='edit' value='edit' onClick="return confirm_edit(frm);" >Edit Selected</button>&nbsp;&nbsp;
-<button class="btn" type="submit" name="delete" value='delete' onClick="return confirm_delete(frm);">Delete Selected</button>
-</form>
-{% endif %}
-
-{% endblock %}
diff --git a/yaksh/templates/yaksh/showquestions.html b/yaksh/templates/yaksh/showquestions.html
index 6222d6d..ca51d1a 100644
--- a/yaksh/templates/yaksh/showquestions.html
+++ b/yaksh/templates/yaksh/showquestions.html
@@ -38,7 +38,6 @@
</div>
<br>
<button class="btn" type="button" onclick='location.replace("{{URL_ROOT}}/exam/manage/addquestion/");'>Add Question</button>&nbsp;&nbsp;
-<button class="btn" type="submit" name='edit' value='edit' onClick="return confirm_edit(frm);">Edit Selected</button>&nbsp;&nbsp;
<button class="btn" type="submit" onClick="return confirm_delete(frm);" name='delete' value='delete'>Delete Selected</button>
</form>
{% endblock %}
diff --git a/yaksh/tests.py b/yaksh/tests.py
index bdc9584..d8e108a 100644
--- a/yaksh/tests.py
+++ b/yaksh/tests.py
@@ -27,7 +27,7 @@ def setUpModule():
# create 20 questions
for i in range(1, 21):
- Question.objects.create(summary='Q%d' % (i), points=1)
+ Question.objects.create(summary='Q%d' % (i), points=1, type='code')
# create a quiz
quiz = Quiz.objects.create(start_date_time=datetime(2015, 10, 9, 10, 8, 15, 0),
@@ -263,12 +263,9 @@ class QuestionPaperTestCases(unittest.TestCase):
self.assertEqual(len(paper_questions), 7)
fixed_questions = set(self.question_paper.fixed_questions.all())
self.assertTrue(fixed_questions.issubset(set(paper_questions)))
- # test is_questionpaper_passed()
answerpaper.passed = True
answerpaper.save()
- self.assertTrue(self.question_paper.is_questionpaper_passed(self.user))
- # test is_attempt_allowed()
- self.assertFalse(self.question_paper.is_attempt_allowed(self.user))
+ self.assertFalse(self.question_paper.is_prerequisite_passed(self.user))
# test can_attempt_now(self):
self.assertFalse(self.question_paper.can_attempt_now(self.user))
@@ -370,6 +367,14 @@ class AnswerPaperTestCases(unittest.TestCase):
self.assertTrue(self.answerpaper.is_answer_correct(self.questions[0]))
self.assertFalse(self.answerpaper.is_answer_correct(self.questions[1]))
+ def test_get_previous_answers(self):
+ answers = self.answerpaper.get_previous_answers(self.questions[0])
+ self.assertEqual(answers.count(), 1)
+ self.assertTrue(answers[0], self.answer_right)
+ answers = self.answerpaper.get_previous_answers(self.questions[1])
+ self.assertEqual(answers.count(), 1)
+ self.assertTrue(answers[0], self.answer_wrong)
+
###############################################################################
class CourseTestCases(unittest.TestCase):
def setUp(self):
diff --git a/yaksh/urls.py b/yaksh/urls.py
index 53c7b8a..3a75947 100644
--- a/yaksh/urls.py
+++ b/yaksh/urls.py
@@ -15,9 +15,9 @@ urlpatterns += patterns('yaksh.views',
url(r'^quizzes/$', 'quizlist_user'),
url(r'^results/$', 'results_user'),
url(r'^start/$', 'start'),
+ url(r'^start/(?P<questionpaper_id>\d+)/$', 'start'),
url(r'^start/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$', 'start'),
url(r'^quit/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$', 'quit'),
- url(r'^intro/(?P<questionpaper_id>\d+)/$', 'intro'),
url(r'^complete/$', 'complete'),
url(r'^complete/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$',\
'complete'),
@@ -25,8 +25,10 @@ urlpatterns += patterns('yaksh.views',
url(r'^(?P<q_id>\d+)/check/$', 'check'),
url(r'^(?P<q_id>\d+)/check/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$',\
'check'),
- url(r'^intro/$', 'intro'),
- url(r'^(?P<q_id>\d+)/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$', 'show_question'),
+ url(r'^(?P<q_id>\d+)/skip/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$',
+ 'skip'),
+ url(r'^(?P<q_id>\d+)/skip/(?P<next_q>\d+)/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$',
+ 'skip'),
url(r'^enroll_request/(?P<course_id>\d+)/$', 'enroll_request'),
url(r'^self_enroll/(?P<course_id>\d+)/$', 'self_enroll'),
@@ -34,15 +36,12 @@ urlpatterns += patterns('yaksh.views',
url(r'^manage/addquestion/$', 'add_question'),
url(r'^manage/addquestion/(?P<question_id>\d+)/$', 'add_question'),
url(r'^manage/addquiz/$', 'add_quiz'),
- url(r'^manage/editquiz/$', 'edit_quiz'),
- url(r'^manage/editquestion/$', 'edit_question'),
url(r'^manage/addquiz/(?P<quiz_id>\d+)/$', 'add_quiz'),
url(r'^manage/gradeuser/$', 'show_all_users'),
url(r'^manage/gradeuser/(?P<username>.*)/(?P<questionpaper_id>\d+)/$',
'grade_user'),
url(r'^manage/gradeuser/(?P<username>.*)/$', 'grade_user'),
url(r'^manage/questions/$', 'show_all_questions'),
- url(r'^manage/showquiz/$', 'show_all_quiz'),
url(r'^manage/monitor/$', 'monitor'),
url(r'^manage/showquestionpapers/$', 'show_all_questionpapers'),
url(r'^manage/showquestionpapers/(?P<questionpaper_id>\d+)/$',\
diff --git a/yaksh/views.py b/yaksh/views.py
index 314814d..c65fb26 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -73,7 +73,7 @@ def index(request):
if user.is_authenticated():
if user.groups.filter(name='moderator').count() > 0:
return my_redirect('/exam/manage/')
- return my_redirect("/exam/start/")
+ return my_redirect("/exam/quizzes/")
return my_redirect("/exam/login/")
@@ -85,7 +85,7 @@ def user_register(request):
user = request.user
ci = RequestContext(request)
if user.is_authenticated():
- return my_redirect("/exam/start/")
+ return my_redirect("/exam/quizzes/")
if request.method == "POST":
form = UserRegisterForm(request.POST)
@@ -94,7 +94,7 @@ def user_register(request):
u_name, pwd = form.save()
new_user = authenticate(username=u_name, password=pwd)
login(request, new_user)
- return my_redirect("/exam/start/")
+ return my_redirect("/exam/quizzes/")
else:
return my_render_to_response('yaksh/register.html', {'form': form},
context_instance=ci)
@@ -120,37 +120,6 @@ def quizlist_user(request):
return my_render_to_response("yaksh/quizzes_user.html", context)
-@login_required
-def intro(request, questionpaper_id=None):
- """Show introduction page before quiz starts"""
- user = request.user
- ci = RequestContext(request)
- if questionpaper_id is None:
- return my_redirect('/exam/quizzes/')
- quest_paper = QuestionPaper.objects.get(id=questionpaper_id)
- if not quest_paper.quiz.course.is_enrolled(user) :
- raise Http404('You are not allowed to view this page!')
- attempt_number = quest_paper.quiz.attempts_allowed
- if quest_paper.quiz.has_prerequisite():
- pre_quest = QuestionPaper.objects.get(quiz=quest_paper.quiz.prerequisite)
- if not pre_quest.is_questionpaper_passed(user):
- return quizlist_user(request)
-
- last_attempt = AnswerPaper.objects.get_user_last_attempt(
- questionpaper=quest_paper, user=user)
- if last_attempt and last_attempt.is_attempt_inprogress():
- return show_question(request, last_attempt.current_question().id,
- last_attempt.attempt_number,
- last_attempt.question_paper.id)
-
- attempt_number = 1 if not last_attempt else last_attempt.attempt_number +1
- if quest_paper.is_attempt_allowed(user) and quest_paper.can_attempt_now(user):
- context = {'user': user, 'questionpaper': quest_paper,
- 'attempt_num': attempt_number}
- return my_render_to_response('yaksh/intro.html', context,
- context_instance=ci)
- return my_redirect("/exam/quizzes/")
-
@login_required
def results_user(request):
@@ -162,79 +131,6 @@ def results_user(request):
@login_required
-def edit_quiz(request):
- """Edit the list of quizzes seleted by the user for editing."""
-
- user = request.user
- if not user.is_authenticated() or not is_moderator(user):
- raise Http404('You are not allowed to view this page!')
- quiz_list = request.POST.getlist('quizzes')
- start_date = request.POST.getlist('start_date')
- start_time = request.POST.getlist('start_time')
- end_date = request.POST.getlist('end_date')
- end_time = request.POST.getlist('end_time')
- 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)
- quiz.start_date_time = datetime.datetime.combine(start_date[j],
- start_time[j])
- quiz.end_date_time = datetime.datetime.combine(end_date[j],
- end_time[j])
- 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/")
-
-
-@login_required
-def edit_question(request):
- """Edit the list of questions selected by the user for editing."""
- user = request.user
- if not user.is_authenticated() or not is_moderator(user):
- raise Http404('You are not allowed to view this page!')
- question_list = request.POST.getlist('questions')
- summary = request.POST.getlist('summary')
- description = request.POST.getlist('description')
- points = request.POST.getlist('points')
- options = request.POST.getlist('options')
- test = request.POST.getlist('test')
- type = request.POST.getlist('type')
- active = request.POST.getlist('active')
- language = request.POST.getlist('language')
- snippet = request.POST.getlist('snippet')
- for j, question_id in enumerate(question_list):
- question = Question.objects.get(id=question_id)
- test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=question)
- if test_case_formset.is_valid():
- test_case_instance = test_case_formset.save(commit=False)
- for i in test_case_instance:
- i.save()
-
- question.summary = summary[j]
- question.description = description[j]
- question.points = points[j]
- question.options = options[j]
- question.active = active[j]
- question.language = language[j]
- question.snippet = snippet[j]
- question.ref_code_path = ref_code_path[j]
- question.test = test[j]
- question.type = type[j]
- question.save()
- return my_redirect("/exam/manage/questions")
-
-
-@login_required
def add_question(request, question_id=None):
"""To add a new question in the database.
Create a new question and store it."""
@@ -262,10 +158,6 @@ def add_question(request, question_id=None):
test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=qtn)
form.save()
question = Question.objects.order_by("-id")[0]
- tags = form['tags'].data.split(',')
- for i in range(0, len(tags)-1):
- tag = tags[i].strip()
- question.tags.add(tag)
if test_case_formset.is_valid():
test_case_formset.save()
else:
@@ -283,39 +175,15 @@ def add_question(request, question_id=None):
else:
d = Question.objects.get(id=question_id)
+ form = QuestionForm(request.POST, instance=d)
test_case_formset = add_or_delete_test_form(request.POST, d)
if 'save_question' in request.POST:
- d.summary = form['summary'].data
- d.description = form['description'].data
- d.points = form['points'].data
- d.options = form['options'].data
- d.type = form['type'].data
- d.active = form['active'].data
- d.language = form['language'].data
- d.snippet = form['snippet'].data
- d.ref_code_path = form['ref_code_path'].data
- d.test = form['test'].data
- d.save()
+ qtn = form.save(commit=False)
+ test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=qtn)
+ form.save()
question = Question.objects.get(id=question_id)
- for tag in question.tags.all():
- question.tags.remove(tag)
- tags = form['tags'].data.split(',')
- for i in range(0, len(tags)-1):
- tag = tags[i].strip()
- question.tags.add(tag)
-
- test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=question)
if test_case_formset.is_valid():
- test_case_instance = test_case_formset.save(commit=False)
- for i in test_case_instance:
- i.save()
- else:
- return my_render_to_response('yaksh/add_question.html',
- {'form': form,
- 'formset': test_case_formset},
- context_instance=ci)
-
-
+ test_case_formset.save()
return my_redirect("/exam/manage/questions")
return my_render_to_response('yaksh/add_question.html',
{'form': form,
@@ -323,14 +191,12 @@ def add_question(request, question_id=None):
context_instance=ci)
else:
- test_case_formset = add_or_delete_test_form(request.POST, form.save(commit=False))
+ test_case_formset = TestCaseFormSet(prefix='test', instance=Question())
return my_render_to_response('yaksh/add_question.html',
{'form': form,
'formset': test_case_formset},
context_instance=ci)
else:
- form = QuestionForm()
- test_case_formset = TestCaseFormSet(prefix='test', instance=Question())
if question_id is None:
form = QuestionForm()
test_case_formset = TestCaseFormSet(prefix='test', instance=Question())
@@ -340,28 +206,8 @@ def add_question(request, question_id=None):
context_instance=ci)
else:
d = Question.objects.get(id=question_id)
- form = QuestionForm()
- form.initial['summary'] = d.summary
- form.initial['description'] = d.description
- form.initial['points'] = d.points
- form.initial['options'] = d.options
- form.initial['type'] = d.type
- form.initial['active'] = d.active
- form.initial['language'] = d.language
- form.initial['snippet'] = d.snippet
- form.initial['ref_code_path'] = d.ref_code_path
- form.initial['test'] = d.test
- form_tags = d.tags.all()
- form_tags_split = form_tags.values('name')
- initial_tags = ""
- for tag in form_tags_split:
- initial_tags = initial_tags + str(tag['name']).strip() + ","
- if (initial_tags == ","):
- initial_tags = ""
- form.initial['tags'] = initial_tags
-
- test_case_formset = TestCaseFormSet(prefix='test',
- instance=d)
+ form = QuestionForm(instance=d)
+ test_case_formset = TestCaseFormSet(prefix='test', instance=d)
return my_render_to_response('yaksh/add_question.html',
{'form': form,
@@ -376,63 +222,33 @@ def add_quiz(request, quiz_id=None):
user = request.user
ci = RequestContext(request)
- if not user.is_authenticated() or not is_moderator(user):
+ if not is_moderator(user):
raise Http404('You are not allowed to view this page!')
+
if request.method == "POST":
- form = QuizForm(request.POST, user=user)
- if form.is_valid():
- data = form.cleaned_data
- if quiz_id is None:
+ if quiz_id is None:
+ form = QuizForm(request.POST, user=user)
+ if form.is_valid():
form.save()
- quiz = Quiz.objects.order_by("-id")[0]
return my_redirect("/exam/manage/designquestionpaper")
- else:
- d = Quiz.objects.get(id=quiz_id)
- sd = datetime.datetime.strptime(form['start_date'].data, '%Y-%m-%d').date()
- st = datetime.datetime.strptime(form['start_time'].data, "%H:%M:%S").time()
- ed = datetime.datetime.strptime(form['end_date'].data, '%Y-%m-%d').date()
- et = datetime.datetime.strptime(form['end_time'].data, "%H:%M:%S").time()
- d.start_date_time = datetime.datetime.combine(sd, st)
- d.end_date_time = datetime.datetime.combine(ed, et)
- 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.attempts_allowed = form['attempts_allowed'].data
- d.time_between_attempts = form['time_between_attempts'].data
- d.save()
- quiz = Quiz.objects.get(id=quiz_id)
- return my_redirect("/exam/manage/showquiz")
else:
- return my_render_to_response('yaksh/add_quiz.html',
- {'form': form},
- context_instance=ci)
+ quiz = Quiz.objects.get(id=quiz_id)
+ form = QuizForm(request.POST, user=user, instance=quiz)
+ if form.is_valid():
+ form.save()
+ return my_redirect("/exam/manage/")
+ return my_render_to_response('yaksh/add_quiz.html',
+ {'form': form},
+ context_instance=ci)
else:
if quiz_id is None:
form = QuizForm(user=user)
- return my_render_to_response('yaksh/add_quiz.html',
- {'form': form},
- context_instance=ci)
else:
- d = Quiz.objects.get(id=quiz_id)
- form = QuizForm(user=user)
- form.initial['start_date'] = d.start_date_time.date()
- form.initial['start_time'] = d.start_date_time.time()
- form.initial['end_date'] = d.end_date_time.date()
- form.initial['end_time'] = d.end_date_time.time()
- 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
- form.initial['attempts_allowed'] = d.attempts_allowed
- form.initial['time_between_attempts'] = d.time_between_attempts
- return my_render_to_response('yaksh/add_quiz.html',
- {'form': form},
- context_instance=ci)
+ quiz = Quiz.objects.get(id=quiz_id)
+ form = QuizForm(user=user, instance=quiz)
+ return my_render_to_response('yaksh/add_quiz.html',
+ {'form': form},
+ context_instance=ci)
@login_required
@@ -442,19 +258,6 @@ def show_all_questionpapers(request, questionpaper_id=None):
if not user.is_authenticated() or not is_moderator(user):
raise Http404('You are not allowed to view this page!')
- if request.method == "POST" and request.POST.get('add') == "add":
- return my_redirect("/exam/manage/designquestionpaper/" +
- questionpaper_id)
-
- if request.method == "POST" and request.POST.get('delete') == "delete":
- data = request.POST.getlist('papers')
- q_paper = QuestionPaper.objects.get(id=questionpaper_id)
- for i in data:
- q_paper.questions.remove(Question.objects.get(id=i))
- question_paper = QuestionPaper.objects.all()
- context = {'papers': question_paper}
- return my_render_to_response('yaksh/showquestionpapers.html', context,
- context_instance=ci)
if questionpaper_id is None:
qu_papers = QuestionPaper.objects.all()
context = {'papers': qu_papers}
@@ -463,8 +266,10 @@ def show_all_questionpapers(request, questionpaper_id=None):
else:
qu_papers = QuestionPaper.objects.get(id=questionpaper_id)
quiz = qu_papers.quiz
- questions = qu_papers.questions.all()
- context = {'papers': {'quiz': quiz, 'questions': questions}}
+ fixed_questions = qu_papers.fixed_questions.all()
+ random_questions = qu_papers.random_questions.all()
+ context = {'quiz': quiz, 'fixed_questions': fixed_questions,
+ 'random_questions': random_questions}
return my_render_to_response('yaksh/editquestionpaper.html', context,
context_instance=ci)
@@ -498,7 +303,7 @@ def user_login(request):
if user.is_authenticated():
if user.groups.filter(name='moderator').count() > 0:
return my_redirect('/exam/manage/')
- return my_redirect("/exam/intro/")
+ return my_redirect("/exam/quizzes/")
if request.method == "POST":
form = UserLoginForm(request.POST)
@@ -519,143 +324,135 @@ def user_login(request):
context_instance=ci)
+
@login_required
-def start(request, attempt_num=None, questionpaper_id=None):
+def start(request, questionpaper_id=None, attempt_num=None):
"""Check the user cedentials and if any quiz is available,
start the exam."""
user = request.user
- if questionpaper_id is None or attempt_num is None:
- return my_redirect('/exam/quizzes/')
+ ci = RequestContext(request)
+ # check conditions
try:
- questionpaper = QuestionPaper.objects.get(id=questionpaper_id)
+ quest_paper = QuestionPaper.objects.get(id=questionpaper_id)
except QuestionPaper.DoesNotExist:
msg = 'Quiz not found, please contact your '\
'instructor/administrator. Please login again thereafter.'
- return complete(request, msg, attempt_num, questionpaper_id)
-
- if not questionpaper.quiz.course.is_enrolled(user):
+ return complete(request, msg, attempt_num, questionpaper_id=None)
+ if not quest_paper.quiz.course.is_enrolled(user) :
raise Http404('You are not allowed to view this page!')
-
- try:
- old_paper = AnswerPaper.objects.get(
- question_paper=questionpaper, user=user, attempt_number=attempt_num)
- q = old_paper.current_question().id
- return show_question(request, q, attempt_num, questionpaper_id)
- except AnswerPaper.DoesNotExist:
+ # prerequisite check and passing criteria
+ if quest_paper.quiz.has_prerequisite() and not quest_paper.is_prerequisite_passed(user):
+ return quizlist_user(request)
+ # if any previous attempt
+ last_attempt = AnswerPaper.objects.get_user_last_attempt(
+ questionpaper=quest_paper, user=user)
+ if last_attempt and last_attempt.is_attempt_inprogress():
+ return show_question(request, last_attempt.current_question(), last_attempt)
+ # allowed to start
+ if not quest_paper.can_attempt_now(user):
+ return quizlist_user(request)
+ if attempt_num is None:
+ attempt_number = 1 if not last_attempt else last_attempt.attempt_number +1
+ context = {'user': user, 'questionpaper': quest_paper,
+ 'attempt_num': attempt_number}
+ return my_render_to_response('yaksh/intro.html', context,
+ context_instance=ci)
+ else:
ip = request.META['REMOTE_ADDR']
try:
profile = user.get_profile()
except Profile.DoesNotExist:
msg = 'You do not have a profile and cannot take the quiz!'
raise Http404(msg)
-
- new_paper = questionpaper.make_answerpaper(user, ip, attempt_num)
+ new_paper = quest_paper.make_answerpaper(user, ip, attempt_num)
# Make user directory.
user_dir = get_user_dir(user)
- return show_question(request, new_paper.current_question().id, attempt_num, questionpaper_id)
+ return show_question(request, new_paper.current_question(), new_paper)
@login_required
-def show_question(request, q_id, attempt_num, questionpaper_id, success_msg=None):
+def show_question(request, question, paper, error_message=None):
"""Show a question if possible."""
user = request.user
- try:
- q_paper = QuestionPaper.objects.get(id=questionpaper_id)
- paper = AnswerPaper.objects.get(
- user=request.user, attempt_number=attempt_num, question_paper=q_paper)
- except AnswerPaper.DoesNotExist:
- return my_redirect('/exam/start/')
- if not q_id:
+ if not question:
msg = 'Congratulations! You have successfully completed the quiz.'
- return complete(request, msg, attempt_num, questionpaper_id)
- else:
- q = get_object_or_404(Question, pk=q_id)
- if not paper.question_paper.quiz.active:
- reason = 'The quiz has been deactivated!'
- return complete(request, reason, attempt_num, questionpaper_id)
- time_left = paper.time_left()
- if time_left == 0:
- reason='Your time is up!'
- return complete(request, reason, attempt_num, questionpaper_id)
- context = {'question': q, 'paper': paper}
- if q.type == 'code':
- skipped_answer = paper.answers.filter(question=q, skipped=True)
- if skipped_answer:
- context['last_attempt'] = skipped_answer[0].answer
- ci = RequestContext(request)
- return my_render_to_response('yaksh/question.html', context,
- context_instance=ci)
+ return complete(request, msg, paper.attempt_number, paper.question_paper.id)
+ if not paper.question_paper.quiz.active:
+ reason = 'The quiz has been deactivated!'
+ return complete(request, reason, paper.attempt_number, paper.question_paper.id)
+ if paper.time_left() <= 0:
+ reason='Your time is up!'
+ return complete(request, reason, paper.attempt_number, paper.question_paper.id)
+ context = {'question': question, 'paper': paper, 'error_message': error_message}
+ answers = paper.get_previous_answers(question)
+ if answers:
+ context['last_attempt'] = answers[0]
+ ci = RequestContext(request)
+ return my_render_to_response('yaksh/question.html', context,
+ context_instance=ci)
-def _save_skipped_answer(old_skipped, user_answer, paper, question):
- """
- Saves the answer on skip. Only the code questions are saved.
- Snippet is not saved with the answer.
- """
- if old_skipped:
- skipped_answer = old_skipped[0]
- skipped_answer.answer=user_answer
- skipped_answer.save()
+@login_required
+def skip(request, q_id, next_q=None, attempt_num=None, questionpaper_id=None):
+ user = request.user
+ paper = get_object_or_404(AnswerPaper, user=request.user, attempt_number=attempt_num,
+ question_paper=questionpaper_id)
+ question = get_object_or_404(Question, pk=q_id)
+ if request.method == 'POST' and question.type == 'code':
+ user_code = request.POST.get('answer')
+ new_answer = Answer(question=question, answer=user_code,
+ correct=False, skipped=True)
+ new_answer.save()
+ paper.answers.add(new_answer)
+ if next_q is None:
+ next_q = paper.skip(q_id) if paper.skip(q_id) else question
else:
- skipped_answer = Answer(question=question, answer=user_answer,
- correct=False, skipped=True)
- skipped_answer.save()
- paper.answers.add(skipped_answer)
+ next_q = get_object_or_404(Question, pk=next_q)
+ return show_question(request, next_q, paper)
+
@login_required
def check(request, q_id, attempt_num=None, questionpaper_id=None):
"""Checks the answers of the user for particular question"""
user = request.user
- q_paper = QuestionPaper.objects.get(id=questionpaper_id)
paper = get_object_or_404(AnswerPaper, user=request.user, attempt_number=attempt_num,
- question_paper=q_paper)
+ question_paper=questionpaper_id)
+ question = get_object_or_404(Question, pk=q_id)
+ if question in paper.questions_answered.all():
+ next_q = paper.skip(q_id)
+ return show_question(request, next_q, paper)
- if q_id in paper.questions_answered.all():
- next_q = paper.skip(q_id).id
- return show_question(request, next_q, attempt_num, questionpaper_id)
+ if request.method == 'POST':
+ snippet_code = request.POST.get('snippet')
+ # Add the answer submitted, regardless of it being correct or not.
+ if question.type == 'mcq':
+ user_answer = request.POST.get('answer')
+ elif question.type == 'mcc':
+ user_answer = request.POST.getlist('answer')
+ elif question.type == 'upload':
+ assign = AssignmentUpload()
+ assign.user = user.profile
+ assign.assignmentQuestion = question
+ # if time-up at upload question then the form is submitted without
+ # validation
+ if 'assignment' in request.FILES:
+ assign.assignmentFile = request.FILES['assignment']
+ assign.save()
+ user_answer = 'ASSIGNMENT UPLOADED'
+ next_q = paper.completed_question(question.id)
+ return show_question(request, next_q, paper)
+ else:
+ user_code = request.POST.get('answer')
+ user_answer = snippet_code + "\n" + user_code if snippet_code else user_code
+ new_answer = Answer(question=question, answer=user_answer,
+ correct=False)
+ new_answer.save()
+ paper.answers.add(new_answer)
- question = get_object_or_404(Question, pk=q_id)
- test_cases = TestCase.objects.filter(question=question)
-
- snippet_code = request.POST.get('snippet')
- user_code = request.POST.get('answer')
- skip = request.POST.get('skip', None)
- success_msg = False
- success = True
- if skip is not None:
- if question.type == 'code':
- old_skipped = paper.answers.filter(question=question, skipped=True)
- _save_skipped_answer(old_skipped, user_code, paper, question)
- next_q = paper.skip(q_id).id if paper.skip(q_id) else q_id
- return show_question(request, next_q, attempt_num, questionpaper_id)
-
- # Add the answer submitted, regardless of it being correct or not.
- if question.type == 'mcq':
- user_answer = request.POST.get('answer')
- elif question.type == 'mcc':
- user_answer = request.POST.getlist('answer')
- elif question.type == 'upload':
- assign = AssignmentUpload()
- assign.user = user.profile
- assign.assignmentQuestion = question
- # if time-up at upload question then the form is submitted without
- # validation
- if 'assignment' in request.FILES:
- assign.assignmentFile = request.FILES['assignment']
- assign.save()
- user_answer = 'ASSIGNMENT UPLOADED'
- else:
- user_code = request.POST.get('answer')
- user_answer = snippet_code + "\n" + user_code if snippet_code else user_code
- new_answer = Answer(question=question, answer=user_answer,
- correct=False)
- new_answer.save()
- paper.answers.add(new_answer)
-
- # If we were not skipped, we were asked to check. For any non-mcq
- # questions, we obtain the results via XML-RPC with the code executed
- # safely in a separate process (the code_server.py) running as nobody.
- if not question.type == 'upload':
+ # If we were not skipped, we were asked to check. For any non-mcq
+ # questions, we obtain the results via XML-RPC with the code executed
+ # safely in a separate process (the code_server.py) running as nobody.
+ test_cases = TestCase.objects.filter(question=question)
json_data = question.consolidate_answer_data(test_cases, user_answer) \
if question.type == 'code' else None
correct, result = validate_answer(user, user_answer, question, json_data)
@@ -663,55 +460,29 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None):
new_answer.correct = correct
new_answer.marks = question.points
new_answer.error = result.get('error')
- success_msg = True
else:
new_answer.error = result.get('error')
new_answer.save()
-
- paper.update_marks('inprogress')
- if paper.time_left() <= 0:
- reason = 'Your time is up!'
- return complete(request, reason, attempt_num, questionpaper_id)
- if not paper.question_paper.quiz.active:
- reason = 'The quiz has been deactivated!'
- return complete(request, reason, attempt_num, questionpaper_id)
- if not result.get('success'): # Should only happen for non-mcq questions.
- old_answer = paper.answers.filter(question=question, skipped=True)
- if old_answer:
- old_answer[0].answer = user_code
- old_answer[0].save()
- context = {'question': question, 'error_message': result.get('error'),
- 'paper': paper}
- ci = RequestContext(request)
-
- return my_render_to_response('yaksh/question.html', context,
- context_instance=ci)
- else:
- # Display the same question if user_answer is None
- if not user_answer:
- ci = RequestContext(request)
- msg = "Please submit a valid option or code"
- context = {'question': question, 'error_message': msg,
- 'paper': paper}
- elif question.type == 'code' and user_answer:
- msg = "Correct Output"
- success = "True"
- paper.completed_question(question.id)
- context = {'question': question, 'paper': paper,
- 'error_message': msg, 'success': success}
- ci = RequestContext(request)
-
- return my_render_to_response('yaksh/question.html', context,
- context_instance=ci)
+ paper.update_marks('inprogress')
+ if not result.get('success'): # Should only happen for non-mcq questions.
+ new_answer.answer = user_code
+ new_answer.save()
+ return show_question(request, question, paper, result.get('error'))
else:
- next_q = paper.completed_question(question.id)
- if next_q:
- next_q = next_q.id
- return show_question(request, next_q, attempt_num,
- questionpaper_id, success_msg)
+ # Display the same question if user_answer is None
+ if not user_answer:
+ msg = "Please submit a valid option or code"
+ return show_question(request, question, paper, msg)
+ elif question.type == 'code' and user_answer:
+ msg = "Correct Output"
+ paper.completed_question(question.id)
+ return show_question(request, question, paper, msg)
+ else:
+ next_q = paper.completed_question(question.id)
+ return show_question(request, next_q, paper)
+ else:
+ return show_question(request, question, paper)
- return my_render_to_response('yaksh/question.html', context,
- context_instance=ci)
def validate_answer(user, user_answer, question, json_data=None):
"""
@@ -770,30 +541,13 @@ def complete(request, reason=None, attempt_num=None, questionpaper_id=None):
attempt_number=attempt_num)
paper.update_marks()
if paper.percent == 100:
- context = {'message': "Hurray ! You did an excellent job.\
- you answered all the questions correctly.\
+ message = "You answered all the questions correctly.\
You have been logged out successfully,\
- Thank You !",
- 'paper': paper}
- return my_render_to_response('yaksh/complete.html', context)
+ Thank You !"
else:
message = reason or "You are successfully logged out"
- context = {'message': message, 'paper': paper}
- return my_render_to_response('yaksh/complete.html', context)
- no = False
- message = reason or 'The quiz has been completed. Thank you.'
- if user.groups.filter(name='moderator').count() > 0:
- message = 'You are successfully Logged out.'
- if request.method == 'POST' and 'no' in request.POST:
- no = True
- if not no:
- # Logout the user and quit with the message given.
- answer_paper = AnswerPaper.objects.get(id=answerpaper_id)
- answer_paper.end_time = datetime.datetime.now()
- answer_paper.save()
- return my_redirect('/exam/quizzes/')
- else:
- return my_redirect('/exam/')
+ context = {'message': message, 'paper': paper}
+ return my_render_to_response('yaksh/complete.html', context)
@login_required
@@ -996,65 +750,6 @@ def show_all_users(request):
context_instance=RequestContext(request))
-@login_required
-def show_all_quiz(request):
- """Generates a list of all the quizzes
- that are currently in the database."""
-
- user = request.user
- ci = RequestContext(request)
- if not user.is_authenticated() or not is_moderator(user):
- raise Http404('You are not allowed to view this page !')
-
- if request.method == 'POST' and request.POST.get('delete') == 'delete':
- data = request.POST.getlist('quiz')
-
- if data is None:
- quizzes = Quiz.objects.all()
- context = {'papers': [],
- 'quiz': None,
- 'quizzes': quizzes}
- return my_render_to_response('yaksh/show_quiz.html', context,
- context_instance=ci)
- else:
- for i in data:
- quiz = Quiz.objects.get(id=i).delete()
- quizzes = Quiz.objects.all()
- context = {'papers': [],
- 'quiz': None,
- 'quizzes': quizzes}
- return my_render_to_response('yaksh/show_quiz.html', context,
- context_instance=ci)
-
- elif request.method == 'POST' and request.POST.get('edit') == 'edit':
- data = request.POST.getlist('quiz')
- forms = []
- for j in data:
- d = Quiz.objects.get(id=j)
- form = QuizForm(user=user)
- form.initial['start_date'] = d.start_date_time.date()
- form.initial['start_time'] = d.start_date_time.time()
- form.initial['end_date'] = d.end_date_time.date()
- form.initial['end_time'] = d.end_date_time.time()
- 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('yaksh/edit_quiz.html',
- {'forms': forms, 'data': data},
- context_instance=ci)
- else:
- quizzes = Quiz.objects.all()
- context = {'papers': [],
- 'quiz': None,
- 'quizzes': quizzes}
- return my_render_to_response('yaksh/show_quiz.html', context,
- context_instance=ci)
-
-
@csrf_exempt
def ajax_questions_filter(request):
"""Ajax call made when filtering displayed questions."""
@@ -1090,73 +785,18 @@ def show_all_questions(request):
if request.method == 'POST' and request.POST.get('delete') == 'delete':
data = request.POST.getlist('question')
- if data is None:
- questions = Question.objects.all()
- form = QuestionFilterForm()
- context = {'papers': [],
- 'question': None,
- 'questions': questions,
- 'form': form
- }
- return my_render_to_response('yaksh/showquestions.html', context,
- context_instance=ci)
- else:
+ if data is not None:
for i in data:
question = Question.objects.get(id=i).delete()
- questions = Question.objects.all()
- form = QuestionFilterForm()
- context = {'papers': [],
- 'question': None,
- 'questions': questions,
- 'form': form
- }
- return my_render_to_response('yaksh/showquestions.html', context,
- context_instance=ci)
- elif request.method == 'POST' and request.POST.get('edit') == 'edit':
- data = request.POST.getlist('question')
-
- forms = []
- formsets = []
- for j in data:
- d = Question.objects.get(id=j)
- form = QuestionForm()
- form.initial['summary'] = d.summary
- form.initial['description'] = d.description
- form.initial['points'] = d.points
- form.initial['options'] = d.options
- form.initial['type'] = d.type
- form.initial['active'] = d.active
- form.initial['language'] = d.language
- form.initial['snippet'] = d.snippet
- form.initial['ref_code_path'] = d.ref_code_path
- form.initial['test'] = d.test
- form_tags = d.tags.all()
- form_tags_split = form_tags.values('name')
- initial_tags = ""
- for tag in form_tags_split:
- initial_tags = initial_tags + str(tag['name']).strip() + ","
- if (initial_tags == ","):
- initial_tags = ""
- form.initial['tags'] = initial_tags
- forms.append(form)
- test_case_formset = TestCaseFormSet(prefix='test', instance=d)
- formsets.append(test_case_formset)
- data_list = zip(forms, formsets)
-
- return my_render_to_response('yaksh/edit_question.html',
- {'data': data,
- 'data_list': data_list},
- context_instance=ci)
- else:
- questions = Question.objects.all()
- form = QuestionFilterForm()
- context = {'papers': [],
- 'question': None,
- 'questions': questions,
- 'form': form
- }
- return my_render_to_response('yaksh/showquestions.html', context,
- context_instance=ci)
+ questions = Question.objects.all()
+ form = QuestionFilterForm()
+ context = {'papers': [],
+ 'question': None,
+ 'questions': questions,
+ 'form': form
+ }
+ return my_render_to_response('yaksh/showquestions.html', context,
+ context_instance=ci)
@login_required
def user_data(request, username, questionpaper_id=None):
@@ -1280,7 +920,7 @@ def design_questionpaper(request):
user = request.user
ci = RequestContext(request)
- if not user.is_authenticated() or not is_moderator(user):
+ if not is_moderator(user):
raise Http404('You are not allowed to view this page!')
if request.method == 'POST':
@@ -1314,9 +954,9 @@ def design_questionpaper(request):
question_paper.random_questions.add(question_set)
question_paper.update_total_marks()
question_paper.save()
- return my_redirect('/exam/manage/showquiz')
+ return my_redirect('/exam/manage/courses')
else:
form = RandomQuestionForm()
- context = {'form': form}
+ context = {'form': form, 'questionpaper':True}
return my_render_to_response('yaksh/design_questionpaper.html',
context, context_instance=ci)