Total number of participants(including multiple attempts): {{ total }}
+
+
Question
Type
Answered
+ {% for question, attempts in question_stats.items %}
+
{{ question.summary }}
{{ question.type }}
{{ attempts }} ({% widthratio attempts total 100 %}%)
+ {% endfor %}
+
+{% endblock %}
diff --git a/yaksh/urls.py b/yaksh/urls.py
index 61222b8..ea6f5e8 100644
--- a/yaksh/urls.py
+++ b/yaksh/urls.py
@@ -50,6 +50,7 @@ urlpatterns = patterns('yaksh.views',
url(r'^manage/designquestionpaper/manual$', 'manual_questionpaper'),
url(r'^manage/designquestionpaper/manual/(?P\d+)/$',\
'manual_questionpaper'),
+ url(r'^manage/statistics/question/(?P\d+)/$','statistics'),
url(r'^ajax/questionpaper/(?P.+)/$', 'ajax_questionpaper'),
url(r'^ajax/questions/filter/$', 'ajax_questions_filter'),
diff --git a/yaksh/views.py b/yaksh/views.py
index 755b33b..4724f98 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -1164,6 +1164,33 @@ def complete(request, reason=None, attempt_num=None, questionpaper_id=None):
else:
return my_redirect('/exam/')
+@login_required
+def statistics(request, questionpaper_id):
+ user = request.user
+ if not is_moderator(user):
+ raise Http404('You are not allowed to view this page')
+ questions_answered = []
+ question_stats = {}
+ papers = AnswerPaper.objects.filter(question_paper_id=questionpaper_id,
+ status='completed')
+ 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)))
+ total_attempt = papers.count()
+ 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}
+ return my_render_to_response('yaksh/statistics_question.html', context,
+ context_instance=RequestContext(request))
+
@login_required
def monitor(request, questionpaper_id=None):
@@ -1520,3 +1547,5 @@ def design_questionpaper(request):
context = {'form': form}
return my_render_to_response('yaksh/design_questionpaper.html',
context, context_instance=ci)
+
+
--
cgit
From acb128c0637c19aebaae0e620b12d918f9544a95 Mon Sep 17 00:00:00 2001
From: prathamesh
Date: Tue, 23 Feb 2016 12:32:37 +0530
Subject: Added a check for zero attempt
---
yaksh/urls.py | 3 ++-
yaksh/views.py | 22 ++++++++++++----------
2 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/yaksh/urls.py b/yaksh/urls.py
index ea6f5e8..096f582 100644
--- a/yaksh/urls.py
+++ b/yaksh/urls.py
@@ -50,7 +50,8 @@ urlpatterns = patterns('yaksh.views',
url(r'^manage/designquestionpaper/manual$', 'manual_questionpaper'),
url(r'^manage/designquestionpaper/manual/(?P\d+)/$',\
'manual_questionpaper'),
- url(r'^manage/statistics/question/(?P\d+)/$','statistics'),
+ url(r'^manage/statistics/question/(?P\d+)/$',
+ 'show_statistics'),
url(r'^ajax/questionpaper/(?P.+)/$', 'ajax_questionpaper'),
url(r'^ajax/questions/filter/$', 'ajax_questions_filter'),
diff --git a/yaksh/views.py b/yaksh/views.py
index 4724f98..bbab12f 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -1164,32 +1164,36 @@ def complete(request, reason=None, attempt_num=None, questionpaper_id=None):
else:
return my_redirect('/exam/')
+
@login_required
-def statistics(request, questionpaper_id):
+def show_statistics(request, questionpaper_id):
user = request.user
if not is_moderator(user):
raise Http404('You are not allowed to view this page')
questions_answered = []
question_stats = {}
papers = AnswerPaper.objects.filter(question_paper_id=questionpaper_id,
- status='completed')
+ status='completed')
+ total_attempt = papers.count()
+ if total_attempt == 0:
+ return my_redirect('/exam/manage/')
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)))
- total_attempt = papers.count()
- questions = Question.objects.filter(id__in=paper.questions.split('|')).\
- order_by('type')
+ 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}
+ 'total': total_attempt}
return my_render_to_response('yaksh/statistics_question.html', context,
- context_instance=RequestContext(request))
+ context_instance=RequestContext(request))
@login_required
@@ -1547,5 +1551,3 @@ def design_questionpaper(request):
context = {'form': form}
return my_render_to_response('yaksh/design_questionpaper.html',
context, context_instance=ci)
-
-
--
cgit
From 0a10f67dcb20984ff294e8f792b5716e5adee0e8 Mon Sep 17 00:00:00 2001
From: prathamesh
Date: Tue, 23 Feb 2016 12:35:35 +0530
Subject: minor shuffle
---
yaksh/views.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/yaksh/views.py b/yaksh/views.py
index bbab12f..72b11d9 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -1170,13 +1170,13 @@ def show_statistics(request, questionpaper_id):
user = request.user
if not is_moderator(user):
raise Http404('You are not allowed to view this page')
- questions_answered = []
- question_stats = {}
papers = AnswerPaper.objects.filter(question_paper_id=questionpaper_id,
status='completed')
total_attempt = papers.count()
if total_attempt == 0:
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
--
cgit
From 815cd103ec67bcea8cdced706138063cecdcef8c Mon Sep 17 00:00:00 2001
From: prathamesh
Date: Tue, 23 Feb 2016 15:45:25 +0530
Subject: Changed as per suggestion
---
yaksh/templates/yaksh/statistics_question.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/yaksh/templates/yaksh/statistics_question.html b/yaksh/templates/yaksh/statistics_question.html
index d9fcd34..dc4786f 100644
--- a/yaksh/templates/yaksh/statistics_question.html
+++ b/yaksh/templates/yaksh/statistics_question.html
@@ -9,7 +9,7 @@
Statistics for {{quiz_name}}
{% endblock %}
{% block manage %}
-
Total number of participants(including multiple attempts): {{ total }}
+
Total number of participants: {{ total }}
Question
Type
Answered
{% for question, attempts in question_stats.items %}
--
cgit
From 3b055ad0ad3232a25408632a020d5e3c284c245b Mon Sep 17 00:00:00 2001
From: prathamesh
Date: Thu, 25 Feb 2016 00:04:01 +0530
Subject: Question Statistics for a quiz per attempt.
Shows the number of appearance of a question versus number of times
the question was answered correctly
---
yaksh/models.py | 82 ++++++++++++++++++++++++++
yaksh/templates/yaksh/statistics_question.html | 25 +++++---
yaksh/urls.py | 2 +
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
@@ -282,6 +283,70 @@ class QuestionSet(models.Model):
return sample(self.questions.all(), self.num_questions)
+###############################################################################
+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 @@
{% endblock %}
{% block subtitle %}
-Statistics for {{quiz_name}}
+Statistics for {{quiz.description}}
{% endblock %}
{% block manage %}
-
Total number of participants: {{ total }}
-
-
Question
Type
Answered
- {% for question, attempts in question_stats.items %}
-
{{ question.summary }}
{{ question.type }}
{{ attempts }} ({% widthratio attempts total 100 %}%)