From bee8835b03a44bf1989bee151c169696bd3c6132 Mon Sep 17 00:00:00 2001 From: Ross Date: Sat, 18 Dec 2021 19:52:39 +0000 Subject: [PATCH] . --- anatomy/urls.py | 6 ++ generic/views.py | 149 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) diff --git a/anatomy/urls.py b/anatomy/urls.py index 6ec0c256..4ff7559c 100644 --- a/anatomy/urls.py +++ b/anatomy/urls.py @@ -82,6 +82,12 @@ urlpatterns = [ # cache_page(60 * 1)(views.exam_scores_cid), name="exam_scores_cid", ), + path( + "exam//scores2", + views.AnatomyExamViews.exam_scores_cid2, + # cache_page(60 * 1)(views.exam_scores_cid), + name="exam_scores_cid", + ), path( "exam//scores/refresh", views.AnatomyExamViews.exam_scores_refresh, diff --git a/generic/views.py b/generic/views.py index 5298198d..61ccf86d 100644 --- a/generic/views.py +++ b/generic/views.py @@ -61,6 +61,27 @@ import plotly.express as px # from rad.views import get_question_and_content_type +def normaliseRapidsScore(score): + if score == 49: + return 4.5 + elif score in [50, 51]: + return 5 + elif score in [52, 53]: + return 5.5 + elif score in [54]: + return 6 + elif score in [55, 56]: + return 6.5 + elif score in [57, 58]: + return 7 + elif score in [59]: + return 7.5 + elif score in [60]: + return 8 + + return 4 + + def get_question_and_content_type(question_type): if question_type == "rapid": question = RapidQuestion @@ -835,6 +856,134 @@ class ExamViews(View, LoginRequiredMixin): cache.set("{}_question_json_{}".format(self.app_name, sk), question_json, 3600) return JsonResponse(question_json) + def exam_scores_cid2(self, request, pk): + exam = get_object_or_404(self.Exam, pk=pk) + + if not exam.exam_mode: + raise Http404("Packet not in exam mode") + + user_answers_and_marks = defaultdict(list) + user_answers_marks = defaultdict(list) + user_answers = defaultdict(list) + user_names = {} + + score_by_question = defaultdict(dict) + ans_by_question = defaultdict(dict) + unmarked = set() + + questions = exam.exam_questions.all() + + cid_user_answers = self.CidUserAnswer.objects.filter(question__in=questions, exam__id=pk) + + cids = set() + + # Loop through all candidates + for cid_user_answer in cid_user_answers: + # Convoluted (probably...) + cid = cid_user_answer.cid + cids.add(cid) + s = cid_user_answer + user_names[cid] = cid + + q = cid_user_answer.question + + # if not s: + # # skip if no answer + # user_answers_marks[cid].append(0) + # user_answers[cid].append("") + # by_question[q].append(("", 0)) + # continue + if s.normal: + ans = "Normal" + else: + 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)) + + score_by_question[q][cid] = answer_score + ans_by_question[q][cid] = ans + + user_scores = {} + user_scores_normalised = {} + for user in user_answers_marks: + user_scores[user] = sum( + [i for i in user_answers_marks[user] if i != "unmarked"] + ) + user_scores_normalised[user] = normaliseRapidsScore( + sum([i for i in user_answers_marks[user] if i != "unmarked"]) + ) + + user_scores_list = list(user_scores.values()) + + max_score = len(questions) * 2 + + 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() + + 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_new.html", + { + "cids": sorted(cids), + "exam": exam, + "unmarked": unmarked, + "questions": questions, + "score_by_question": score_by_question, + "ans_by_question": ans_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, + }, + ) def exam_scores_cid(self, request, pk): exam = get_object_or_404(self.Exam, pk=pk)