diff options
-rw-r--r-- | yaksh/models.py | 82 | ||||
-rw-r--r-- | yaksh/templates/yaksh/statistics_question.html | 25 | ||||
-rw-r--r-- | yaksh/urls.py | 2 | ||||
-rw-r--r-- | yaksh/views.py | 39 |
4 files changed, 119 insertions, 29 deletions
diff --git a/yaksh/models.py b/yaksh/models.py index 712c455..8415930 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -2,6 +2,7 @@ import datetime import json from random import sample, shuffle from itertools import islice, cycle +from collections import Counter from django.db import models from django.contrib.auth.models import User from taggit.managers import TaggableManager @@ -283,6 +284,70 @@ class QuestionSet(models.Model): ############################################################################### +class AnswerPaperManager(models.Manager): + def get_all_questions(self, questionpaper_id, attempt_number, + status='completed'): + ''' Return a dict of question id as key and count as value''' + papers = self.filter(question_paper_id=questionpaper_id, + attempt_number=attempt_number, status=status) + questions = list() + for paper in papers: + questions += paper.get_questions() + return Counter(map(int, questions)) + + def get_all_questions_answered(self, questionpaper_id, attempt_number, + status='completed'): + ''' Return a dict of answered question id as key and count as value''' + papers = self.filter(question_paper_id=questionpaper_id, + attempt_number=attempt_number, status=status) + questions_answered = list() + for paper in papers: + for question in filter(None, paper.get_questions_answered()): + if paper.is_answer_correct(question): + questions_answered.append(question) + return Counter(map(int, questions_answered)) + + def get_attempt_numbers(self, questionpaper_id, status='completed'): + ''' Return list of attempt numbers''' + attempt_numbers = self.filter( + question_paper_id=questionpaper_id, status=status + ).values_list('attempt_number', flat=True).distinct() + return attempt_numbers + + def has_attempt(self, questionpaper_id, attempt_number, status='completed'): + ''' Whether question paper is attempted''' + return self.filter(question_paper_id=questionpaper_id, + attempt_number=attempt_number, status=status).exists() + + def get_count(self, questionpaper_id, attempt_number, status='completed'): + ''' Return count of answerpapers for a specfic question paper + and attempt number''' + return self.filter(question_paper_id=questionpaper_id, + attempt_number=attempt_number, status=status).count() + + def get_question_statistics(self, questionpaper_id, attempt_number, + status='completed'): + ''' Return dict with question object as key and list as value + The list contains two value, first the number of times a question + was answered correctly, and second the number of times a question + appeared in a quiz''' + question_stats = {} + questions_answered = self.get_all_questions_answered(questionpaper_id, + attempt_number) + questions = self.get_all_questions(questionpaper_id, attempt_number) + all_questions = Question.objects.filter( + id__in=set(questions) + ).order_by('type') + for question in all_questions: + if question.id in questions_answered: + question_stats[question] = [questions_answered[question.id], + questions[question.id]] + else: + question_stats[question] = [0, questions[question.id]] + return question_stats + + +############################################################################### class AnswerPaper(models.Model): """A answer paper for a student -- one per student typically. """ @@ -330,6 +395,8 @@ class AnswerPaper(models.Model): status = models.CharField(max_length=20, choices=test_status,\ default='inprogress') + objects = AnswerPaperManager() + def current_question(self): """Returns the current active question to display.""" qu = self.get_unanswered_questions() @@ -448,6 +515,19 @@ class AnswerPaper(models.Model): q_a[question] = [answer] return q_a + def get_questions(self): + ''' Return a list of questions''' + return self.questions.split('|') + + def get_questions_answered(self): + ''' Return a list of questions answered''' + return self.questions_answered.split('|') + + def is_answer_correct(self, question_id): + ''' Return marks of a question answered''' + return self.answers.filter(question_id=question_id, + correct=True).exists() + def __unicode__(self): u = self.user return u'Question paper for {0} {1}'.format(u.first_name, u.last_name) @@ -475,3 +555,5 @@ class TestCase(models.Model): # Test case Expected answer in list form expected_answer = models.TextField(blank=True, null = True) + + diff --git a/yaksh/templates/yaksh/statistics_question.html b/yaksh/templates/yaksh/statistics_question.html index dc4786f..a63844f 100644 --- a/yaksh/templates/yaksh/statistics_question.html +++ b/yaksh/templates/yaksh/statistics_question.html @@ -6,14 +6,25 @@ <link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/question_quiz.css" type="text/css" /> {% endblock %} {% block subtitle %} -Statistics for {{quiz_name}} +Statistics for {{quiz.description}} {% endblock %} {% block manage %} -<p><b>Total number of participants: {{ total }}</b></p> -<table class="bordered-table zebra-striped"> - <tr><th>Question</th><th>Type</th><th>Answered</th></tr> - {% for question, attempts in question_stats.items %} - <tr><td>{{ question.summary }}</td><td>{{ question.type }}</td><td>{{ attempts }} ({% widthratio attempts total 100 %}%)</td></tr> +<div class="row"> + <div class="span2"> +{% for attempt in attempts %} + <p><a href="{{URL_ROOT}}/exam/manage/statistics/question/{{questionpaper_id}}/{{attempt}}">Attempt {{ attempt }}</a></p> {% endfor %} -</table> +</div> +<div class="span10"> +{% if question_stats %} + <p><b>Total number of participants: {{ total }}</b></p> + <table class="bordered-table zebra-striped"> + <tr><th>Question</th><th>Type</th><th>Total</th><th>Answered</th></tr> + {% for question, value in question_stats.items %} + <tr><td>{{ question.summary }}</td><td>{{ question.type }}</td><td>{{value.1}}</td><td>{{ value.0 }} ({% widthratio value.0 value.1 100 %}%)</td></tr> + {% endfor %} + </table> + {% endif %} + </div> +</div> {% endblock %} diff --git a/yaksh/urls.py b/yaksh/urls.py index 096f582..e6c2e15 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -52,6 +52,8 @@ urlpatterns = patterns('yaksh.views', 'manual_questionpaper'), url(r'^manage/statistics/question/(?P<questionpaper_id>\d+)/$', 'show_statistics'), + url(r'^manage/statistics/question/(?P<questionpaper_id>\d+)/(?P<attempt_number>\d+)/$', + 'show_statistics'), url(r'^ajax/questionpaper/(?P<query>.+)/$', 'ajax_questionpaper'), url(r'^ajax/questions/filter/$', 'ajax_questions_filter'), diff --git a/yaksh/views.py b/yaksh/views.py index 72b11d9..6558427 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -1166,32 +1166,27 @@ def complete(request, reason=None, attempt_num=None, questionpaper_id=None): @login_required -def show_statistics(request, questionpaper_id): +def show_statistics(request, questionpaper_id, attempt_number=None): user = request.user if not is_moderator(user): raise Http404('You are not allowed to view this page') - papers = AnswerPaper.objects.filter(question_paper_id=questionpaper_id, - status='completed') - total_attempt = papers.count() - if total_attempt == 0: + attempt_numbers = AnswerPaper.objects.get_attempt_numbers(questionpaper_id) + quiz = get_object_or_404(QuestionPaper, pk=questionpaper_id).quiz + if attempt_number is None: + context = {'quiz': quiz, 'attempts': attempt_numbers, + 'questionpaper_id': questionpaper_id} + return my_render_to_response('yaksh/statistics_question.html', context, + context_instance=RequestContext(request)) + total_attempt = AnswerPaper.objects.get_count(questionpaper_id, + attempt_number) + if not AnswerPaper.objects.has_attempt(questionpaper_id, attempt_number): return my_redirect('/exam/manage/') - questions_answered = [] - question_stats = {} - for paper in papers: - questions_answered += paper.questions_answered.split('|') - quiz_name = paper.question_paper.quiz.description - questions_answered = collections.Counter(map(int, filter(None, - questions_answered))) - questions = Question.objects.filter( - id__in=paper.questions.split('|') - ).order_by('type') - for question in questions: - if question.id in questions_answered: - question_stats[question] = questions_answered[question.id] - else: - question_stats[question] = 0 - context = {'question_stats': question_stats, 'quiz_name': quiz_name, - 'total': total_attempt} + question_stats = AnswerPaper.objects.get_question_statistics( + questionpaper_id, attempt_number + ) + context = {'question_stats': question_stats, 'quiz': quiz, + 'questionpaper_id': questionpaper_id, + 'attempts': attempt_numbers, 'total': total_attempt} return my_render_to_response('yaksh/statistics_question.html', context, context_instance=RequestContext(request)) |