diff options
author | Prabhu Ramachandran | 2016-04-07 17:51:28 +0530 |
---|---|---|
committer | Prabhu Ramachandran | 2016-04-07 17:51:28 +0530 |
commit | 2dfef7f76cb04b34901650dc9ae0f41ef394d6ba (patch) | |
tree | 4650dadd7c00a4bd8930aff86faacbcaf0593d3d | |
parent | 69d53a33c77270a9244344d9de676d39502a9f1b (diff) | |
parent | b9f96f3edc315fbcab6752cf13c65dd127ab5bd1 (diff) | |
download | online_test-2dfef7f76cb04b34901650dc9ae0f41ef394d6ba.tar.gz online_test-2dfef7f76cb04b34901650dc9ae0f41ef394d6ba.tar.bz2 online_test-2dfef7f76cb04b34901650dc9ae0f41ef394d6ba.zip |
Merge pull request #90 from prathamesh920/views_cleanup_phase_2
Views cleanup phase 2
-rw-r--r-- | yaksh/forms.py | 102 | ||||
-rw-r--r-- | yaksh/models.py | 24 | ||||
-rw-r--r-- | yaksh/templates/yaksh/automatic_questionpaper.html | 87 | ||||
-rw-r--r-- | yaksh/templates/yaksh/edit_question.html | 61 | ||||
-rw-r--r-- | yaksh/templates/yaksh/edit_quiz.html | 39 | ||||
-rw-r--r-- | yaksh/templates/yaksh/editquestionpaper.html | 15 | ||||
-rw-r--r-- | yaksh/templates/yaksh/manual_questionpaper.html | 79 | ||||
-rw-r--r-- | yaksh/templates/yaksh/question.html | 18 | ||||
-rw-r--r-- | yaksh/templates/yaksh/quizlist.html | 24 | ||||
-rw-r--r-- | yaksh/templates/yaksh/quizzes_user.html | 4 | ||||
-rw-r--r-- | yaksh/templates/yaksh/show_quiz.html | 33 | ||||
-rw-r--r-- | yaksh/templates/yaksh/showquestions.html | 1 | ||||
-rw-r--r-- | yaksh/tests.py | 15 | ||||
-rw-r--r-- | yaksh/urls.py | 11 | ||||
-rw-r--r-- | yaksh/views.py | 688 |
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;"> <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> {{ question.active }}{{question.active.errors}} Type: {{ 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 }}"> <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 }}"> <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 }}"> <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> -<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> - <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> {% 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> -{% 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}} /> <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> -<button class="btn" type="submit" name='edit' value='edit' onClick="return confirm_edit(frm);" >Edit Selected</button> -<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> -<button class="btn" type="submit" name='edit' value='edit' onClick="return confirm_edit(frm);">Edit Selected</button> <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) |