This commit is contained in:
Ross
2022-06-26 19:01:48 +01:00
parent 695a07f2e2
commit f454d5a08d
16 changed files with 544 additions and 94 deletions
+152 -33
View File
@@ -1,4 +1,4 @@
from collections import defaultdict
from collections import defaultdict, Counter
import statistics
import threading
from dal import autocomplete
@@ -294,7 +294,9 @@ class ExamViews(View, LoginRequiredMixin):
# exam_group = group_map[self.app_name]
class ExamFilter(FilterSet):
sort_order = OrderingFilter(fields=(("name", "name"), ("exam_mode", "exam_mode")))
sort_order = OrderingFilter(
fields=(("name", "name"), ("exam_mode", "exam_mode"))
)
class Meta:
model = exam
@@ -529,16 +531,15 @@ class ExamViews(View, LoginRequiredMixin):
def exam_list(self, request, all=False):
if not self.check_user_access(request.user):
#raise PermissionDenied
exam_list = self.Exam.objects.filter(author__id=request.user.id).order_by("name")
# raise PermissionDenied
exam_list = self.Exam.objects.filter(author__id=request.user.id).order_by(
"name"
)
else:
exam_list = self.Exam.objects.all().order_by("name")
if not all:
exams = exam_list.filter(exam_mode=True, archive=False).order_by(
"name"
)
exams = exam_list.filter(exam_mode=True, archive=False).order_by("name")
marking = False
@@ -556,6 +557,90 @@ class ExamViews(View, LoginRequiredMixin):
},
)
@method_decorator(login_required)
def exam_report_email_status(self, request, exam_id):
exam = get_object_or_404(self.Exam.objects.prefetch_related("author"), pk=exam_id)
if request.user not in exam.author.all():
if not self.check_user_access(request.user, exam_id):
raise PermissionDenied
users = [i[2:] for i in exam.user_scores if i.startswith("u/")]
status = {}
for u in users:
user = User.objects.get(pk=u)
user_exam = exam.get_or_create_cid_user_exam(user_user=user)
status[user.username] = user_exam.results_emailed_status
return JsonResponse(status)
@method_decorator(login_required)
def exam_report_email(self, request, exam_id):
exam = get_object_or_404(self.Exam.objects.prefetch_related("author"), pk=exam_id)
if request.user not in exam.author.all():
if not self.check_user_access(request.user, exam_id):
raise PermissionDenied
# We only need to send emails to those who have scores
# (who should be in exam.user_scores)
users = [i[2:] for i in exam.user_scores if i.startswith("u/")]
time = timezone.now()
email_results = {}
for u in users:
user = User.objects.get(pk=u)
email_results[user.username] = exam.email_user_results(user)
user_exam = exam.get_or_create_cid_user_exam(user_user=user)
user_exam.results_emailed_status = json.dumps(email_results[user.username]) + f" {time}"
user_exam.save()
exam.exam_results_emailed = time
exam.save()
return JsonResponse(email_results)
@method_decorator(login_required)
def exam_user_report_email(self, request, exam_id, user_id):
# print(Exam.objects.all())
# exams = Exam.objects.all()
# print("test", Exam.objects.all().get(id=pk))
exam = get_object_or_404(self.Exam.objects.prefetch_related("author"), pk=exam_id)
u = get_object_or_404(User, pk=user_id)
if request.user not in exam.author.all():
if not self.check_user_access(request.user, exam_id):
raise PermissionDenied
res = exam.email_user_results(u)
return HttpResponse(res)
@method_decorator(login_required)
def exam_user_report(self, request, exam_id, user_id):
# print(Exam.objects.all())
# exams = Exam.objects.all()
# print("test", Exam.objects.all().get(id=pk))
exam = get_object_or_404(self.Exam.objects.prefetch_related("author"), pk=exam_id)
u = get_object_or_404(User, pk=user_id)
if request.user not in exam.author.all():
if not self.check_user_access(request.user, exam_id):
raise PermissionDenied
res = exam.generate_user_report(u)
print(res)
return HttpResponse(res)
@method_decorator(login_required)
def exam_overview(self, request, pk):
# print(Exam.objects.all())
@@ -563,6 +648,7 @@ class ExamViews(View, LoginRequiredMixin):
# print("test", Exam.objects.all().get(id=pk))
exam = get_object_or_404(self.Exam.objects.prefetch_related("author"), pk=pk)
if request.user not in exam.author.all():
if not self.check_user_access(request.user, pk):
raise PermissionDenied
@@ -1396,6 +1482,10 @@ class ExamViews(View, LoginRequiredMixin):
by_question = defaultdict(dict)
unmarked = set()
if self.app_name in ("rapids"):
user_answers_callstates = defaultdict(list)
user_answers_callstates_counted = {}
if self.app_name in ("physics", "sbas"):
questions = exam.exam_questions.all()
else:
@@ -1408,15 +1498,18 @@ class ExamViews(View, LoginRequiredMixin):
cids = set()
cids_user_id_map = {}
# Loop through all candidates
for cid_user_answer in cid_user_answers:
# Convoluted (probably...)
if cid_user_answer.user is None:
cid = cid_user_answer.cid
# cid_passcodes[cid] = cid_user_answer.passcode
cids.add(cid)
cids.add("c/"+cid)
else:
cid = f"u/{cid_user_answer.user.username}"
cid = f"u/{cid_user_answer.user.pk}"
cids_user_id_map[cid] = cid_user_answer.user.username
cids.add(cid)
s = cid_user_answer
@@ -1439,9 +1532,15 @@ class ExamViews(View, LoginRequiredMixin):
unmarked.add(index)
user_answers[cid].append(ans)
user_answers_marks[cid].append(answer_score)
# user_answers_and_marks[cid].append((ans, answer_score))
if self.app_name in ("rapids", "anatomy", "sbas"):
if self.app_name == "rapids":
callstate = s.get_answer_callstate()
print(cid, callstate)
by_question[q][cid] = (ans, answer_score, callstate)
user_answers_callstates[cid].append(callstate)
print(user_answers_callstates)
print("CID:::",cid, user_answers_callstates[cid])
elif self.app_name in ("rapids", "anatomy", "sbas"):
by_question[q][cid] = (ans, answer_score)
else:
zipped_ans_scores = zip(ans, answer_score)
@@ -1513,33 +1612,53 @@ class ExamViews(View, LoginRequiredMixin):
exam.stats_graph = fig_html
exam.user_scores = user_scores
user_data = {}
for u in cids:
#uid = cids_user_id_map[u]
user_data[u] = {
"score": user_scores[u],
"normalised_score": user_scores_normalised[u],
}
if self.app_name == "rapids":
counted_callstates = dict(Counter(user_answers_callstates[u]))
user_data[u]["callstates"] = str(counted_callstates)
user_answers_callstates_counted[u] = counted_callstates
print(user_data)
exam.user_scores = user_data
exam.save()
template_variables = {
"cids": sorted(cids),
# "cid_passcodes": cid_passcodes,
"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_normalised": user_scores_normalised,
# "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,
}
if self.app_name == "rapids":
template_variables["user_answers_callstates"] = user_answers_callstates_counted
return render(
request,
f"{self.app_name}/exam_scores_new.html",
{
"cids": sorted(cids),
# "cid_passcodes": cid_passcodes,
"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_normalised": user_scores_normalised,
# "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,
},
template_variables,
)