.
This commit is contained in:
+1
-1
@@ -78,7 +78,7 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"exam/<int:pk>/scores",
|
"exam/<int:pk>/scores",
|
||||||
views.exam_scores_cid,
|
views.AnatomyExamViews.exam_scores_cid,
|
||||||
# cache_page(60 * 1)(views.exam_scores_cid),
|
# cache_page(60 * 1)(views.exam_scores_cid),
|
||||||
name="exam_scores_cid",
|
name="exam_scores_cid",
|
||||||
),
|
),
|
||||||
|
|||||||
+118
-118
@@ -475,124 +475,124 @@ def exam_scores_refresh(request, pk):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@login_required
|
#@login_required
|
||||||
def exam_scores_cid(request, pk):
|
#def exam_scores_cid(request, pk):
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
# exam = get_object_or_404(Exam, pk=pk)
|
||||||
|
#
|
||||||
if not exam.exam_mode:
|
# if not exam.exam_mode:
|
||||||
raise Http404("Packet not in exam mode")
|
# raise Http404("Packet not in exam mode")
|
||||||
|
#
|
||||||
questions = exam.exam_questions.all()
|
# questions = exam.exam_questions.all()
|
||||||
|
#
|
||||||
cids = (
|
# cids = (
|
||||||
CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
|
# CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
|
||||||
.order_by("cid")
|
# .order_by("cid")
|
||||||
.values_list("cid", flat=True)
|
# .values_list("cid", flat=True)
|
||||||
.distinct()
|
# .distinct()
|
||||||
)
|
# )
|
||||||
|
#
|
||||||
user_answers_and_marks = defaultdict(list)
|
# user_answers_and_marks = defaultdict(list)
|
||||||
user_answers_marks = defaultdict(list)
|
# user_answers_marks = defaultdict(list)
|
||||||
user_answers = defaultdict(list)
|
# user_answers = defaultdict(list)
|
||||||
user_names = {}
|
# user_names = {}
|
||||||
|
#
|
||||||
by_question = defaultdict(list)
|
# by_question = defaultdict(list)
|
||||||
unmarked = set()
|
# unmarked = set()
|
||||||
|
#
|
||||||
# Loop through all candidates
|
# # Loop through all candidates
|
||||||
for cid in cids:
|
# for cid in cids:
|
||||||
# Convoluted (probably...)
|
# # Convoluted (probably...)
|
||||||
user_names[cid] = cid
|
# user_names[cid] = cid
|
||||||
for q in questions:
|
# for q in questions:
|
||||||
# Get user answer
|
# # Get user answer
|
||||||
s = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
|
# s = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
|
||||||
if not s:
|
# if not s:
|
||||||
# skip if no answer
|
# # skip if no answer
|
||||||
user_answers_marks[cid].append(0)
|
# user_answers_marks[cid].append(0)
|
||||||
user_answers[cid].append("")
|
# user_answers[cid].append("")
|
||||||
by_question[q].append(("", 0))
|
# by_question[q].append(("", 0))
|
||||||
continue
|
# continue
|
||||||
|
#
|
||||||
ans = s.answer
|
# ans = s.answer
|
||||||
answer_score = s.get_answer_score()
|
# answer_score = s.get_answer_score()
|
||||||
if answer_score == "unmarked":
|
# if answer_score == "unmarked":
|
||||||
index = exam.get_question_index(q)
|
# index = exam.get_question_index(q)
|
||||||
unmarked.add(index)
|
# unmarked.add(index)
|
||||||
user_answers[cid].append(ans)
|
# user_answers[cid].append(ans)
|
||||||
user_answers_marks[cid].append(answer_score)
|
# user_answers_marks[cid].append(answer_score)
|
||||||
user_answers_and_marks[cid].append((ans, answer_score))
|
# user_answers_and_marks[cid].append((ans, answer_score))
|
||||||
|
#
|
||||||
by_question[q].append((ans, answer_score))
|
# by_question[q].append((ans, answer_score))
|
||||||
|
#
|
||||||
user_scores = {}
|
# user_scores = {}
|
||||||
for user in user_answers_marks:
|
# for user in user_answers_marks:
|
||||||
user_scores[user] = sum(
|
# user_scores[user] = sum(
|
||||||
[i for i in user_answers_marks[user] if i != "unmarked"]
|
# [i for i in user_answers_marks[user] if i != "unmarked"]
|
||||||
)
|
# )
|
||||||
|
#
|
||||||
user_scores_list = list(user_scores.values())
|
# user_scores_list = list(user_scores.values())
|
||||||
|
#
|
||||||
if len(user_scores_list) < 1:
|
# if len(user_scores_list) < 1:
|
||||||
mean = 0
|
# mean = 0
|
||||||
median = 0
|
# median = 0
|
||||||
mode = 0
|
# mode = 0
|
||||||
fig_html = ""
|
# fig_html = ""
|
||||||
else:
|
# else:
|
||||||
mean = statistics.mean(user_scores_list)
|
# mean = statistics.mean(user_scores_list)
|
||||||
median = statistics.median(user_scores_list)
|
# median = statistics.median(user_scores_list)
|
||||||
try:
|
# try:
|
||||||
mode = statistics.mode(user_scores_list)
|
# mode = statistics.mode(user_scores_list)
|
||||||
except statistics.StatisticsError:
|
# except statistics.StatisticsError:
|
||||||
mode = "No unique mode"
|
# mode = "No unique mode"
|
||||||
|
#
|
||||||
df = user_scores_list
|
# df = user_scores_list
|
||||||
fig = px.histogram(
|
# fig = px.histogram(
|
||||||
df,
|
# df,
|
||||||
x=0,
|
# x=0,
|
||||||
title="{}: distribution of scores".format(exam),
|
# title="{}: distribution of scores".format(exam),
|
||||||
labels={"0": "Score"},
|
# labels={"0": "Score"},
|
||||||
height=400,
|
# height=400,
|
||||||
width=600,
|
# width=600,
|
||||||
)
|
# )
|
||||||
fig_html = fig.to_html()
|
# fig_html = fig.to_html()
|
||||||
|
#
|
||||||
max_score = len(questions) * 2
|
# max_score = len(questions) * 2
|
||||||
|
#
|
||||||
exam.stats_mean = mean
|
# exam.stats_mean = mean
|
||||||
exam.stats_median = median
|
# exam.stats_median = median
|
||||||
exam.stats_mode = mode
|
# exam.stats_mode = mode
|
||||||
|
#
|
||||||
exam.stats_candidates = len(user_scores_list)
|
# exam.stats_candidates = len(user_scores_list)
|
||||||
exam.stats_max_possible = max_score
|
# exam.stats_max_possible = max_score
|
||||||
|
#
|
||||||
exam.stats_min = min(user_scores_list)
|
# exam.stats_min = min(user_scores_list)
|
||||||
exam.stats_max = max(user_scores_list)
|
# exam.stats_max = max(user_scores_list)
|
||||||
|
#
|
||||||
exam.stats_graph = fig_html
|
# exam.stats_graph = fig_html
|
||||||
exam.save()
|
# exam.save()
|
||||||
|
#
|
||||||
return render(
|
# return render(
|
||||||
request,
|
# request,
|
||||||
"anatomy/exam_scores.html",
|
# "anatomy/exam_scores.html",
|
||||||
{
|
# {
|
||||||
"cids": cids,
|
# "cids": cids,
|
||||||
"exam": exam,
|
# "exam": exam,
|
||||||
"unmarked": unmarked,
|
# "unmarked": unmarked,
|
||||||
"questions": questions,
|
# "questions": questions,
|
||||||
"by_question": by_question,
|
# "by_question": by_question,
|
||||||
"user_answers": dict(user_answers),
|
# "user_answers": dict(user_answers),
|
||||||
"user_answers_marks": dict(user_answers_marks),
|
# "user_answers_marks": dict(user_answers_marks),
|
||||||
"user_scores": user_scores,
|
# "user_scores": user_scores,
|
||||||
"user_scores_list": user_scores_list,
|
# "user_scores_list": user_scores_list,
|
||||||
"user_names": user_names,
|
# "user_names": user_names,
|
||||||
"user_answers_and_marks": user_answers_and_marks,
|
# "user_answers_and_marks": user_answers_and_marks,
|
||||||
"max_score": max_score,
|
# "max_score": max_score,
|
||||||
"mean": mean,
|
# "mean": mean,
|
||||||
"median": median,
|
# "median": median,
|
||||||
"mode": mode,
|
# "mode": mode,
|
||||||
"plot": fig_html,
|
# "plot": fig_html,
|
||||||
},
|
# },
|
||||||
)
|
# )
|
||||||
|
|
||||||
|
|
||||||
def exam_scores_cid_user(request, pk, sk, passcode):
|
def exam_scores_cid_user(request, pk, sk, passcode):
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
from collections import defaultdict
|
||||||
|
import statistics
|
||||||
from dal import autocomplete
|
from dal import autocomplete
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
@@ -54,6 +56,7 @@ from datetime import datetime
|
|||||||
import os
|
import os
|
||||||
import string
|
import string
|
||||||
import random
|
import random
|
||||||
|
import plotly.express as px
|
||||||
|
|
||||||
# from rad.views import get_question_and_content_type
|
# from rad.views import get_question_and_content_type
|
||||||
|
|
||||||
@@ -833,6 +836,129 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
|
|
||||||
return JsonResponse(question_json)
|
return JsonResponse(question_json)
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def exam_scores_cid(self, request, pk):
|
||||||
|
exam = get_object_or_404(self.Exam, pk=pk)
|
||||||
|
|
||||||
|
if request.user not in exam.author.all():
|
||||||
|
if not self.check_user_access(request.user, pk):
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
|
if not exam.exam_mode:
|
||||||
|
raise Http404("Packet not in exam mode")
|
||||||
|
|
||||||
|
questions = exam.exam_questions.all()
|
||||||
|
|
||||||
|
cids = (
|
||||||
|
self.CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
|
||||||
|
.order_by("cid")
|
||||||
|
.values_list("cid", flat=True)
|
||||||
|
.distinct()
|
||||||
|
)
|
||||||
|
|
||||||
|
user_answers_and_marks = defaultdict(list)
|
||||||
|
user_answers_marks = defaultdict(list)
|
||||||
|
user_answers = defaultdict(list)
|
||||||
|
user_names = {}
|
||||||
|
|
||||||
|
by_question = defaultdict(list)
|
||||||
|
unmarked = set()
|
||||||
|
|
||||||
|
# Loop through all candidates
|
||||||
|
for cid in cids:
|
||||||
|
# Convoluted (probably...)
|
||||||
|
user_names[cid] = cid
|
||||||
|
for q in questions:
|
||||||
|
# Get user answer
|
||||||
|
s = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
|
||||||
|
if not s:
|
||||||
|
# skip if no answer
|
||||||
|
user_answers_marks[cid].append(0)
|
||||||
|
user_answers[cid].append("")
|
||||||
|
by_question[q].append(("", 0))
|
||||||
|
continue
|
||||||
|
|
||||||
|
ans = s.answer
|
||||||
|
answer_score = s.get_answer_score()
|
||||||
|
if answer_score == "unmarked":
|
||||||
|
index = exam.get_question_index(q)
|
||||||
|
unmarked.add(index)
|
||||||
|
user_answers[cid].append(ans)
|
||||||
|
user_answers_marks[cid].append(answer_score)
|
||||||
|
user_answers_and_marks[cid].append((ans, answer_score))
|
||||||
|
|
||||||
|
by_question[q].append((ans, answer_score))
|
||||||
|
|
||||||
|
user_scores = {}
|
||||||
|
for user in user_answers_marks:
|
||||||
|
user_scores[user] = sum(
|
||||||
|
[i for i in user_answers_marks[user] if i != "unmarked"]
|
||||||
|
)
|
||||||
|
|
||||||
|
user_scores_list = list(user_scores.values())
|
||||||
|
|
||||||
|
if len(user_scores_list) < 1:
|
||||||
|
mean = 0
|
||||||
|
median = 0
|
||||||
|
mode = 0
|
||||||
|
fig_html = ""
|
||||||
|
else:
|
||||||
|
mean = statistics.mean(user_scores_list)
|
||||||
|
median = statistics.median(user_scores_list)
|
||||||
|
try:
|
||||||
|
mode = statistics.mode(user_scores_list)
|
||||||
|
except statistics.StatisticsError:
|
||||||
|
mode = "No unique mode"
|
||||||
|
|
||||||
|
df = user_scores_list
|
||||||
|
fig = px.histogram(
|
||||||
|
df,
|
||||||
|
x=0,
|
||||||
|
title="{}: distribution of scores".format(exam),
|
||||||
|
labels={"0": "Score"},
|
||||||
|
height=400,
|
||||||
|
width=600,
|
||||||
|
)
|
||||||
|
fig_html = fig.to_html()
|
||||||
|
|
||||||
|
max_score = len(questions) * 2
|
||||||
|
|
||||||
|
exam.stats_mean = mean
|
||||||
|
exam.stats_median = median
|
||||||
|
exam.stats_mode = mode
|
||||||
|
|
||||||
|
exam.stats_candidates = len(user_scores_list)
|
||||||
|
exam.stats_max_possible = max_score
|
||||||
|
|
||||||
|
exam.stats_min = min(user_scores_list)
|
||||||
|
exam.stats_max = max(user_scores_list)
|
||||||
|
|
||||||
|
exam.stats_graph = fig_html
|
||||||
|
exam.save()
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
f"{self.app_name}/exam_scores.html",
|
||||||
|
{
|
||||||
|
"cids": cids,
|
||||||
|
"exam": exam,
|
||||||
|
"unmarked": unmarked,
|
||||||
|
"questions": questions,
|
||||||
|
"by_question": by_question,
|
||||||
|
"user_answers": dict(user_answers),
|
||||||
|
"user_answers_marks": dict(user_answers_marks),
|
||||||
|
"user_scores": user_scores,
|
||||||
|
"user_scores_list": user_scores_list,
|
||||||
|
"user_names": user_names,
|
||||||
|
"user_answers_and_marks": user_answers_and_marks,
|
||||||
|
"max_score": max_score,
|
||||||
|
"mean": mean,
|
||||||
|
"median": median,
|
||||||
|
"mode": mode,
|
||||||
|
"plot": fig_html,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class GenericViewBase:
|
class GenericViewBase:
|
||||||
def __init__(self, app_name, QuestionObject, CidUserAnswerObject, ExamObject):
|
def __init__(self, app_name, QuestionObject, CidUserAnswerObject, ExamObject):
|
||||||
|
|||||||
+24
-24
@@ -16,12 +16,14 @@ from generic.models import CidUser, ExamBase, QuestionNote
|
|||||||
|
|
||||||
import reversion
|
import reversion
|
||||||
|
|
||||||
|
|
||||||
class Category(models.Model):
|
class Category(models.Model):
|
||||||
category = models.CharField(max_length=200)
|
category = models.CharField(max_length=200)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.category
|
return self.category
|
||||||
|
|
||||||
|
|
||||||
class Question(models.Model):
|
class Question(models.Model):
|
||||||
stem = models.TextField(
|
stem = models.TextField(
|
||||||
blank=False,
|
blank=False,
|
||||||
@@ -34,9 +36,7 @@ class Question(models.Model):
|
|||||||
blank=False,
|
blank=False,
|
||||||
help_text="The question text",
|
help_text="The question text",
|
||||||
)
|
)
|
||||||
a_answer = models.BooleanField(
|
a_answer = models.BooleanField(help_text=answer_help_text, default=True)
|
||||||
help_text=answer_help_text, default=True
|
|
||||||
)
|
|
||||||
a_feedback = models.TextField(
|
a_feedback = models.TextField(
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="Feedback for answer",
|
help_text="Feedback for answer",
|
||||||
@@ -46,9 +46,7 @@ class Question(models.Model):
|
|||||||
blank=False,
|
blank=False,
|
||||||
help_text="The question text",
|
help_text="The question text",
|
||||||
)
|
)
|
||||||
b_answer = models.BooleanField(
|
b_answer = models.BooleanField(help_text=answer_help_text, default=True)
|
||||||
help_text=answer_help_text, default=True
|
|
||||||
)
|
|
||||||
b_feedback = models.TextField(
|
b_feedback = models.TextField(
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="Feedback for answer",
|
help_text="Feedback for answer",
|
||||||
@@ -58,9 +56,7 @@ class Question(models.Model):
|
|||||||
blank=False,
|
blank=False,
|
||||||
help_text="The question text",
|
help_text="The question text",
|
||||||
)
|
)
|
||||||
c_answer = models.BooleanField(
|
c_answer = models.BooleanField(help_text=answer_help_text, default=True)
|
||||||
help_text=answer_help_text, default=True
|
|
||||||
)
|
|
||||||
c_feedback = models.TextField(
|
c_feedback = models.TextField(
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="Feedback for answer",
|
help_text="Feedback for answer",
|
||||||
@@ -70,9 +66,7 @@ class Question(models.Model):
|
|||||||
blank=False,
|
blank=False,
|
||||||
help_text="The question text",
|
help_text="The question text",
|
||||||
)
|
)
|
||||||
d_answer = models.BooleanField(
|
d_answer = models.BooleanField(help_text=answer_help_text, default=True)
|
||||||
help_text=answer_help_text, default=True
|
|
||||||
)
|
|
||||||
d_feedback = models.TextField(
|
d_feedback = models.TextField(
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="Feedback for answer",
|
help_text="Feedback for answer",
|
||||||
@@ -82,9 +76,7 @@ class Question(models.Model):
|
|||||||
blank=False,
|
blank=False,
|
||||||
help_text="The question text",
|
help_text="The question text",
|
||||||
)
|
)
|
||||||
e_answer = models.BooleanField(
|
e_answer = models.BooleanField(help_text=answer_help_text, default=True)
|
||||||
help_text=answer_help_text, default=True
|
|
||||||
)
|
|
||||||
e_feedback = models.TextField(
|
e_feedback = models.TextField(
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="Feedback for answer",
|
help_text="Feedback for answer",
|
||||||
@@ -124,7 +116,13 @@ class Question(models.Model):
|
|||||||
return reverse("physics:question_detail", kwargs={"pk": self.pk})
|
return reverse("physics:question_detail", kwargs={"pk": self.pk})
|
||||||
|
|
||||||
def get_answers(self):
|
def get_answers(self):
|
||||||
return [self.a_answer, self.b_answer, self.c_answer, self.d_answer, self.e_answer]
|
return [
|
||||||
|
self.a_answer,
|
||||||
|
self.b_answer,
|
||||||
|
self.c_answer,
|
||||||
|
self.d_answer,
|
||||||
|
self.e_answer,
|
||||||
|
]
|
||||||
|
|
||||||
def get_answers_js(self):
|
def get_answers_js(self):
|
||||||
return str(self.get_answers()).lower()
|
return str(self.get_answers()).lower()
|
||||||
@@ -137,9 +135,7 @@ class Question(models.Model):
|
|||||||
class Exam(ExamBase):
|
class Exam(ExamBase):
|
||||||
app_name = "physics"
|
app_name = "physics"
|
||||||
|
|
||||||
exam_questions = SortedManyToManyField(
|
exam_questions = SortedManyToManyField(Question, related_name="exams", blank="true")
|
||||||
Question, related_name="exams", blank="true"
|
|
||||||
)
|
|
||||||
|
|
||||||
time_limit = models.IntegerField(
|
time_limit = models.IntegerField(
|
||||||
help_text="Exam time limit (in seconds)",
|
help_text="Exam time limit (in seconds)",
|
||||||
@@ -149,12 +145,16 @@ class Exam(ExamBase):
|
|||||||
|
|
||||||
recreate_json = None
|
recreate_json = None
|
||||||
|
|
||||||
author = models.ManyToManyField(settings.AUTH_USER_MODEL,
|
author = models.ManyToManyField(
|
||||||
|
settings.AUTH_USER_MODEL,
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text='Author of exam',
|
help_text="Author of exam",
|
||||||
related_name="physics_exam_author")
|
related_name="physics_exam_author",
|
||||||
|
)
|
||||||
|
|
||||||
valid_users = models.ManyToManyField(CidUser, blank=True, related_name="physics_exams")
|
valid_users = models.ManyToManyField(
|
||||||
|
CidUser, blank=True, related_name="physics_exams"
|
||||||
|
)
|
||||||
|
|
||||||
def get_take_url(self):
|
def get_take_url(self):
|
||||||
return reverse("physics:exam_start", kwargs={"pk": self.pk})
|
return reverse("physics:exam_start", kwargs={"pk": self.pk})
|
||||||
@@ -189,7 +189,7 @@ class CidUserAnswer(models.Model):
|
|||||||
def get_answers(self):
|
def get_answers(self):
|
||||||
return (self.a, self.b, self.c, self.d, self.e)
|
return (self.a, self.b, self.c, self.d, self.e)
|
||||||
|
|
||||||
def get_answer_scores(self):
|
def get_answer_score(self):
|
||||||
q = self.question
|
q = self.question
|
||||||
|
|
||||||
if self.a == q.a_answer:
|
if self.a == q.a_answer:
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
|
|
||||||
{% extends 'physics/base.html' %}
|
{% extends 'physics/base.html' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
CID: {{ciduseranswer.cid}}<br/>
|
CID: {{ciduseranswer.cid}}<br />
|
||||||
Exam: {{ciduseranswer.exam}}<br/>
|
Exam: {{ciduseranswer.exam}}<br />
|
||||||
{{ciduseranswer.question}}<br/>
|
{{ciduseranswer.question}}<br />
|
||||||
Answers: <br/>
|
Answers: <br />
|
||||||
<ol>
|
<ol>
|
||||||
<li>{{ciduseranswer.a}}</li>
|
<li>{{ciduseranswer.a}}</li>
|
||||||
<li>{{ciduseranswer.b}}</li>
|
<li>{{ciduseranswer.b}}</li>
|
||||||
@@ -13,6 +12,6 @@ Answers: <br/>
|
|||||||
<li>{{ciduseranswer.d}}</li>
|
<li>{{ciduseranswer.d}}</li>
|
||||||
<li>{{ciduseranswer.e}}</li>
|
<li>{{ciduseranswer.e}}</li>
|
||||||
</ol>
|
</ol>
|
||||||
Score: {{ciduseranswer.get_answer_scores}}<br/>
|
Score: {{ciduseranswer.get_answer_score}}<br />
|
||||||
<a href="{% url 'physics:user_answer_delete' ciduseranswer.id %}">Delete answer</a>
|
<a href="{% url 'physics:user_answer_delete' ciduseranswer.id %}">Delete answer</a>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
+19
-6
@@ -91,6 +91,9 @@ def active_exams(request):
|
|||||||
def exam_scores_cid(request, pk):
|
def exam_scores_cid(request, pk):
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
exam = get_object_or_404(Exam, pk=pk)
|
||||||
|
|
||||||
|
if not exam.exam_mode:
|
||||||
|
raise Http404("Packet not in exam mode")
|
||||||
|
|
||||||
questions = exam.exam_questions.all()
|
questions = exam.exam_questions.all()
|
||||||
|
|
||||||
cids = (
|
cids = (
|
||||||
@@ -117,13 +120,21 @@ def exam_scores_cid(request, pk):
|
|||||||
s = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
|
s = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
|
||||||
if not s:
|
if not s:
|
||||||
# skip if no answer
|
# skip if no answer
|
||||||
user_answers_marks[cid].append((0,0,0,0,0))
|
user_answers_marks[cid].append((0, 0, 0, 0, 0))
|
||||||
user_answers[cid].append(("", "", "", "", ""))
|
user_answers[cid].append(("", "", "", "", ""))
|
||||||
by_question[q].append((("", 0),("", 0),("", 0),("", 0),("", 0),))
|
by_question[q].append(
|
||||||
|
(
|
||||||
|
("", 0),
|
||||||
|
("", 0),
|
||||||
|
("", 0),
|
||||||
|
("", 0),
|
||||||
|
("", 0),
|
||||||
|
)
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
ans = s.get_answers()
|
ans = s.get_answers()
|
||||||
answer_scores = s.get_answer_scores()
|
answer_scores = s.get_answer_score()
|
||||||
|
|
||||||
user_answers[cid].append(ans)
|
user_answers[cid].append(ans)
|
||||||
user_answers_marks[cid].append(answer_scores)
|
user_answers_marks[cid].append(answer_scores)
|
||||||
@@ -212,7 +223,7 @@ def exam_scores_cid_user(request, pk, sk, passcode):
|
|||||||
|
|
||||||
ans = user_answer.get_answers()
|
ans = user_answer.get_answers()
|
||||||
|
|
||||||
answer_scores = user_answer.get_answer_scores()
|
answer_scores = user_answer.get_answer_score()
|
||||||
|
|
||||||
correct_answers = q.get_answers()
|
correct_answers = q.get_answers()
|
||||||
|
|
||||||
@@ -235,7 +246,7 @@ def exam_scores_cid_user(request, pk, sk, passcode):
|
|||||||
{
|
{
|
||||||
"exam": exam,
|
"exam": exam,
|
||||||
"cid": cid,
|
"cid": cid,
|
||||||
"passcode" : passcode,
|
"passcode": passcode,
|
||||||
"questions": questions,
|
"questions": questions,
|
||||||
"answers": answers,
|
"answers": answers,
|
||||||
"answers_marks": answers_marks,
|
"answers_marks": answers_marks,
|
||||||
@@ -452,7 +463,9 @@ def loadJsonAnswer(answer):
|
|||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
|
|
||||||
PhysicsExamViews = ExamViews(Exam, Question, CidUserAnswer, "physics", "physics", loadJsonAnswer)
|
PhysicsExamViews = ExamViews(
|
||||||
|
Exam, Question, CidUserAnswer, "physics", "physics", loadJsonAnswer
|
||||||
|
)
|
||||||
|
|
||||||
GenericViews = GenericViewBase("physics", Question, CidUserAnswer, Exam)
|
GenericViews = GenericViewBase("physics", Question, CidUserAnswer, Exam)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user