summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrabhu Ramachandran2011-11-21 02:41:27 +0530
committerPrabhu Ramachandran2011-11-21 02:41:27 +0530
commitc2185243e9e3e8a66a2a4c7a549d9bc00fd9f2fa (patch)
tree6109a8f027139e8d86d58bc0cb6f147b29c31d9c
parent8f7b25c5639dbe7912df35ea94dfb665d74d0107 (diff)
downloadonline_test-c2185243e9e3e8a66a2a4c7a549d9bc00fd9f2fa.tar.gz
online_test-c2185243e9e3e8a66a2a4c7a549d9bc00fd9f2fa.tar.bz2
online_test-c2185243e9e3e8a66a2a4c7a549d9bc00fd9f2fa.zip
ENH: Better monitor reporting and user_data info
This checkin adds the following: - /exam/monitor displays all available quizzes. - /exam/monitor/quiz_id displays results for the specified quiz. - /exam/user_data/username displays the users data including answers. - A link is provided in monitor output to see user data. - More monitor data like number of attempts. - The monitor and user data are only shown for a user who is authenticated and is staff.
-rw-r--r--exam/urls.py2
-rw-r--r--exam/views.py112
-rw-r--r--templates/exam/monitor.html41
-rw-r--r--templates/exam/user_data.html38
4 files changed, 178 insertions, 15 deletions
diff --git a/exam/urls.py b/exam/urls.py
index e517adb..129a83f 100644
--- a/exam/urls.py
+++ b/exam/urls.py
@@ -8,6 +8,8 @@ urlpatterns = patterns('exam.views',
url(r'^quit/$', 'quit'),
url(r'^complete/$', 'complete'),
url(r'^monitor/$', 'monitor'),
+ url(r'^monitor/(?P<quiz_id>\d+)/$', 'monitor'),
+ url(r'^user_data/(?P<username>[a-zA-Z0-9_.]+)/$', 'user_data'),
url(r'^(?P<q_id>\d+)/$', 'question'),
url(r'^(?P<q_id>\d+)/check/$', 'check'),
)
diff --git a/exam/views.py b/exam/views.py
index 0bec977..7f1f7cf 100644
--- a/exam/views.py
+++ b/exam/views.py
@@ -8,7 +8,10 @@ import datetime
from django.contrib.auth import login, logout, authenticate
from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.template import RequestContext
-from exam.models import Quiz, Question, QuestionPaper, Profile, Answer
+from django.http import Http404
+
+# Local imports.
+from exam.models import Quiz, Question, QuestionPaper, Profile, Answer, User
from exam.forms import UserRegisterForm, UserLoginForm
from exam.xmlrpc_clients import python_server
from settings import URL_ROOT
@@ -150,7 +153,10 @@ def question(request, q_id):
try:
paper = QuestionPaper.objects.get(user=request.user)
except QuestionPaper.DoesNotExist:
- my_redirect('/exam/start')
+ return my_redirect('/exam/start')
+ if not paper.quiz.active:
+ return complete(request, reason='The quiz has been deactivated!')
+
time_left = paper.time_left()
if time_left == 0:
return complete(request, reason='Your time is up!')
@@ -204,6 +210,8 @@ def check(request, q_id):
time_left = paper.time_left()
if time_left == 0:
return complete(request, reason='Your time is up!')
+ if not paper.quiz.active:
+ return complete(request, reason='The quiz has been deactivated!')
context = {'question': question, 'error_message': err_msg,
'paper': paper, 'last_attempt': answer,
@@ -234,13 +242,36 @@ def complete(request, reason=None):
else:
return my_redirect('/exam/')
-def monitor(request):
+def monitor(request, quiz_id=None):
"""Monitor the progress of the papers taken so far."""
- q_papers = QuestionPaper.objects.all()
- questions = Question.objects.all()
- # Mapping from question id to points
- marks = dict( ( (q.id, q.points) for q in questions) )
- paper_list = []
+ user = request.user
+ if not user.is_authenticated() and not user.is_staff:
+ raise Http404('You are not allowed to view this page!')
+
+ if quiz_id is None:
+ quizzes = Quiz.objects.all()
+ quiz_data = {}
+ for quiz in quizzes:
+ quiz_data[quiz.id] = quiz.description
+ context = {'paper_list': [],
+ 'quiz_name': '',
+ 'quiz_data':quiz_data}
+ return my_render_to_response('exam/monitor.html', context,
+ context_instance=RequestContext(request))
+
+ quiz_data = {}
+ try:
+ quiz = Quiz.objects.get(active=True)
+ except Quiz.DoesNotExist:
+ q_papers = []
+ quiz = None
+ else:
+ q_papers = QuestionPaper.objects.filter(quiz=quiz)
+ questions = Question.objects.all()
+ # Mapping from question id to points
+ marks = dict( ( (q.id, q.points) for q in questions) )
+
+ paper_list = []
for q_paper in q_papers:
paper = {}
user = q_paper.user
@@ -249,18 +280,79 @@ def monitor(request):
except Profile.DoesNotExist:
# Admin user may have a paper by accident but no profile.
continue
- paper['username'] = str(user.first_name) + ' ' + str(user.last_name)
+ paper['name'] = user.get_full_name()
+ paper['username'] = user.username
paper['rollno'] = str(profile.roll_number)
qa = q_paper.questions_answered.split('|')
answered = ', '.join(sorted(qa))
paper['answered'] = answered if answered else 'None'
+ paper['attempts'] = q_paper.answers.count()
total = sum( [marks[int(id)] for id in qa if id] )
paper['total'] = total
paper_list.append(paper)
+ if quiz is None:
+ quiz_name = 'No active quiz'
+ elif len(quiz.description) > 0:
+ quiz_name = quiz.description
+ else:
+ quiz_name = 'Quiz'
+
paper_list.sort(cmp=lambda x, y: cmp(x['total'], y['total']),
reverse=True)
- context = {'paper_list': paper_list}
+ context = {'paper_list': paper_list, 'quiz_name': quiz_name}
return my_render_to_response('exam/monitor.html', context,
context_instance=RequestContext(request))
+
+def user_data(request, username):
+ current_user = request.user
+ if not current_user.is_authenticated() and not current_user.is_staff:
+ raise Http404('You are not allowed to view this page!')
+
+ try:
+ user = User.objects.get(username=username)
+ except User.DoesNotExist:
+ q_papers = []
+ else:
+ q_papers = QuestionPaper.objects.filter(user=user)
+ questions = Question.objects.all()
+ # Mapping from question id to points
+ marks = dict( ( (q.id, q.points) for q in questions) )
+
+ data = {}
+ try:
+ profile = Profile.objects.get(user=user)
+ except Profile.DoesNotExist:
+ # Admin user may have a paper by accident but no profile.
+ profile = None
+ data['username'] = user.username
+ data['email'] = user.email
+ data['rollno'] = profile.roll_number if profile else ''
+ data['name'] = user.get_full_name()
+ papers = []
+ for q_paper in q_papers:
+ paper = {}
+ paper['name'] = q_paper.quiz.description
+ qa = q_paper.questions_answered.split('|')
+ answered = ', '.join(sorted(qa))
+ paper['answered'] = answered if answered else 'None'
+ paper['attempts'] = q_paper.answers.count()
+ total = sum( [marks[int(id)] for id in qa if id] )
+ paper['total'] = total
+ answers = {}
+ for answer in q_paper.answers.all():
+ qs = answer.question.summary
+ code = '#'*80 + '\n' + str(answer.answer) + '\n'
+ if qs in answers:
+ answers[qs] += code
+ else:
+ answers[qs] = code
+ paper['answers'] = answers
+ papers.append(paper)
+ data['papers'] = papers
+
+ context = {'user_data': data}
+ return my_render_to_response('exam/user_data.html', context,
+ context_instance=RequestContext(request))
+ \ No newline at end of file
diff --git a/templates/exam/monitor.html b/templates/exam/monitor.html
index d79bb35..201e5db 100644
--- a/templates/exam/monitor.html
+++ b/templates/exam/monitor.html
@@ -5,26 +5,57 @@
{% block meta %} <meta http-equiv="refresh" content="30"/> {% endblock meta %}
{% block content %}
-<h1> Current quiz results </h1>
+{% if not quiz_data and not paper_list %}
+<h1> Quiz results </h1>
+<p> No quizzes available. </p>
+
+{% endif %}
+
+{# ############################################################### #}
+{# This is rendered when we are just viewing exam/monitor #}
+{% if quiz_data %}
+<h1> Available quizzes </h1>
+
+<ul>
+{% for quiz_id, quiz_name in quiz_data.items %}
+<li><a href="{{URL_ROOT}}/exam/monitor/{{quiz_id}}/">{{ quiz_name }}</a></li>
+{% endfor %}
+</ul>
+{% endif %}
+
+{# ############################################################### #}
+{# This is rendered when we are just viewing exam/monitor/quiz_num #}
{% if paper_list %}
+<h1> {{ quiz_name }} results </h1>
+
+{# <p> Quiz: {{ quiz_name }}</p> #}
+<p>Number of papers: {{ paper_list|length }} </p>
+
<table border="1" cellpadding="3">
<tr>
- <th>Student </th> <th> Roll number </th> <th>Questions answered</th> <th>Total marks</th>
+ <th> Name </th>
+ <th> Username </th>
+ <th> Roll number </th>
+ <th> Questions answered </th>
+ <th> Total marks </th>
+ <th> Attempts </th>
</tr>
{% for paper in paper_list %}
<tr>
- <td> {{ paper.username }} </td>
+ <td> <a href="{{URL_ROOT}}/exam/user_data/{{paper.username}}">{{ paper.name }}</a> </td>
+ <td> <a href="{{URL_ROOT}}/exam/user_data/{{paper.username}}">{{ paper.username }}</a> </td>
<td> {{ paper.rollno }} </td>
<td> {{ paper.answered }} </td>
<td> {{ paper.total }} </td>
-
+ <td> {{ paper.attempts }} </td>
</tr>
{% endfor %}
</table>
-{% else %}
+{% else %} {% if quiz_name %}
<p> No answer papers so far. </p>
+ {% endif %}
{% endif %}
{% endblock content %}
diff --git a/templates/exam/user_data.html b/templates/exam/user_data.html
new file mode 100644
index 0000000..7560903
--- /dev/null
+++ b/templates/exam/user_data.html
@@ -0,0 +1,38 @@
+{% extends "base.html" %}
+
+{% block title %} Data for user {{ user_data.name }} {% endblock title %}
+
+{% block content %}
+
+<h1> Data for user {{ user_data.name }} </h1>
+
+<p> Name: {{ user_data.name }} </p>
+<p> Username: {{ user_data.username }} </p>
+<p> Roll number: {{ user_data.rollno }} </p>
+<p> Email: {{ user_data.email }} </p>
+
+{% if user_data.papers %}
+
+{% for paper in user_data.papers %}
+
+<h2> Quiz: {{ paper.name }} </h2>
+
+<p> Answered questions: {{ paper.answered }} </p>
+<p> Total attempts at questions: {{ paper.attempts }} </p>
+<p> Total marks: {{ paper.total }} </p>
+
+{% if paper.answers %}
+<h3> Answers </h3>
+{% for question, answer in paper.answers.items %}
+<h4> Question summary: {{ question }} </h4>
+<pre>
+{{ answer|safe }}
+</pre>
+{% endfor %}
+{% endif %} {# if paper.answers #}
+
+{% endfor %} {# for paper in user_data.papers #}
+
+{% endif %} {# if user_data.papers #}
+
+{% endblock content %}