From 45e038ccd6c7753dbb86854568681fbe27b52c5a Mon Sep 17 00:00:00 2001 From: Ross Date: Sat, 5 Dec 2020 16:04:36 +0000 Subject: [PATCH] numerous improvements --- anatomy/models.py | 16 +++- anatomy/static/css/anatomy.css | 16 ++++ anatomy/static/js/anatomy.js | 14 +++ anatomy/templates/anatomy/cid_scores.html | 13 +++ anatomy/templates/anatomy/exam_overview.html | 29 ++++++ .../templates/anatomy/exam_scores_user.html | 2 +- anatomy/templates/anatomy/mark_overview.html | 10 ++- anatomy/urls.py | 2 + anatomy/views.py | 88 ++++++++++++------- 9 files changed, 151 insertions(+), 39 deletions(-) create mode 100644 anatomy/templates/anatomy/cid_scores.html diff --git a/anatomy/models.py b/anatomy/models.py index d204a133..70ce9b0f 100644 --- a/anatomy/models.py +++ b/anatomy/models.py @@ -136,6 +136,9 @@ class AnatomyQuestion(models.Model): return unmarked_answers + def GetUnmarkedAnswerCount(self): + return len(self.GetUnmarkedAnswers()) + def GetMarkedAnswers(self): return set([i.get_compare_string() for i in self.answers.all() if i.status != i.MarkOptions.UNMARKED]) correct_answers = set([i.answer.lower() for i in self.answers.all()]) @@ -289,4 +292,15 @@ class CidUserAnswer(models.Model): self.answer.strip() def get_compare_string(self): - return self.answer.lower() \ No newline at end of file + return self.answer.lower() + + def get_answer_score(self): + q = self.question + ans = self.answer + if q.answers.filter(answer__iexact=ans, status=Answer.MarkOptions.CORRECT).first() is not None: + mark = 2 + elif q.answers.filter(answer__iexact=ans, status=Answer.MarkOptions.HALF_MARK).first() is not None: + mark = 1 + else: + mark = 0 + return mark \ No newline at end of file diff --git a/anatomy/static/css/anatomy.css b/anatomy/static/css/anatomy.css index 7b6218fa..cdd471a0 100644 --- a/anatomy/static/css/anatomy.css +++ b/anatomy/static/css/anatomy.css @@ -3,6 +3,10 @@ body { background-color: black; } +a, a:link { + color: #3282b8; +} + .warn { color: red; } @@ -107,4 +111,16 @@ button a { .marking { float: right; +} + +#question-mark-list { + padding: 20px +} + +#question-mark-list a { + color: #bbe1fa +} + +#question-mark-list li { + padding-bottom: 5px; } \ No newline at end of file diff --git a/anatomy/static/js/anatomy.js b/anatomy/static/js/anatomy.js index 6757c773..6bec6d96 100644 --- a/anatomy/static/js/anatomy.js +++ b/anatomy/static/js/anatomy.js @@ -82,6 +82,20 @@ cornerstone.loadAndCacheImage(imageId).then(function(image) { }); } +if ($("#question-mark-list").length) { +$(".show-all-button").click(() => { + $("#question-mark-list li").show(); +}); +$(".show-unmarked-button").click(() => { + console.log("TESTIG"); + $("#question-mark-list li").each((n, el) => { + console.log(el); + if (el.dataset.markcount < 1) { $(el).hide(); } + }) +}); + +} + }); function prepAnswerData() { diff --git a/anatomy/templates/anatomy/cid_scores.html b/anatomy/templates/anatomy/cid_scores.html new file mode 100644 index 00000000..fcde81bf --- /dev/null +++ b/anatomy/templates/anatomy/cid_scores.html @@ -0,0 +1,13 @@ +{% extends 'anatomy/base.html' %} + +{% block content %} +
+

CID: {{ cid }}

+ The following exams have been found (click to view answers and scores): + +
+{% endblock %} diff --git a/anatomy/templates/anatomy/exam_overview.html b/anatomy/templates/anatomy/exam_overview.html index f8020a77..6cf139cb 100644 --- a/anatomy/templates/anatomy/exam_overview.html +++ b/anatomy/templates/anatomy/exam_overview.html @@ -6,6 +6,10 @@

Exam: {{ exam.name }}

This exam has {{question_number}} questions. + +
+Exam active: +

@@ -22,4 +26,29 @@ Exams: {{ question.GetExams }} / Modality: {{ question.modality }} Refresh JSON cache
+ {% endblock %} \ No newline at end of file diff --git a/anatomy/templates/anatomy/exam_scores_user.html b/anatomy/templates/anatomy/exam_scores_user.html index 9e30e089..1bbce2f1 100644 --- a/anatomy/templates/anatomy/exam_scores_user.html +++ b/anatomy/templates/anatomy/exam_scores_user.html @@ -1,4 +1,4 @@ -{% extends 'anatomy/exams.html' %} +{% extends 'anatomy/base.html' %} {% block content %}
diff --git a/anatomy/templates/anatomy/mark_overview.html b/anatomy/templates/anatomy/mark_overview.html index 3921f773..977fdd01 100644 --- a/anatomy/templates/anatomy/mark_overview.html +++ b/anatomy/templates/anatomy/mark_overview.html @@ -3,11 +3,15 @@ {% block content %}

Marking exam: {{ exam.name }}

- Question order will be different on the test system (as it is randomly generated) + Question order may be different on the test system (as json order is not guaranteed to be maintained) -
    +
    + +
    + + diff --git a/anatomy/urls.py b/anatomy/urls.py index e2679031..ec4d60f8 100644 --- a/anatomy/urls.py +++ b/anatomy/urls.py @@ -18,10 +18,12 @@ urlpatterns = [ name="exam_scores_cid"), path("exam//scores//", views.exam_scores_cid_user, name="exam_scores_cid_user"), + path("exam//toggle_active", views.exam_toggle_active, name="exam_toggle_active"), path("exam/submit", views.postExamAnswers, name="exam_answers_submit"), path("exam/", views.exam_list, name="exam_list"), path("exam/json/", views.active_exams, name="active_exams"), path("exam/json/", views.exam_json, name="exam_json"), path("exam/json//recreate", views.exam_json_recreate, name="exam_json_recreate"), + path("cid//scores", views.cid_scores, name="cid_scores"), path("ajax/exam/flag/", views.flag_question, name="flag_question"), ] diff --git a/anatomy/views.py b/anatomy/views.py index 9b32db60..591aa300 100644 --- a/anatomy/views.py +++ b/anatomy/views.py @@ -436,6 +436,18 @@ def mark(request, pk, sk): }, ) +def exam_toggle_active(request, pk): + if request.is_ajax() and request.method=='POST': + + exam = get_object_or_404(Exam, pk=pk) + + exam.active = True if request.POST.get('active') == 'true' else False + exam.save() + data = {'status':'success', 'active':exam.active} + return JsonResponse(data, status=200) + else: + data = {'status':'error'} + return JsonResponse(data, status=400) def active_exams(request): exams = Exam.objects.all() @@ -602,24 +614,21 @@ def exam_scores_cid_user(request, pk, sk): for q in questions: # Get user answer - s = q.cid_user_answers.filter(cid=cid) - if not s: + user_answer = q.cid_user_answers.filter(cid=cid).first() + if not user_answer: # skip if no answer answers_marks.append(0) answers.append("") continue - ans = s[0].answer - if q.answers.filter(answer__iexact=ans, status=Answer.MarkOptions.CORRECT).first() is not None: - a = 2 - elif q.answers.filter(answer__iexact=ans, status=Answer.MarkOptions.HALF_MARK).first() is not None: - a = 1 - else: - a = 0 + ans = user_answer.answer + + answer_score = user_answer.get_answer_score() + correct_answer = q.GetPrimaryAnswer() answers.append(ans) - answers_marks.append(a) - answers_and_marks.append((ans, a, correct_answer)) + answers_marks.append(answer_score) + answers_and_marks.append((ans, answer_score, correct_answer)) total_score = sum(answers_marks) @@ -658,39 +667,22 @@ def exam_scores(request, pk): # Convoluted (probably...) user_names[u] = User.objects.filter(pk=u[0]).first().get_username() for q in questions: - s = q.user_answers.filter(user__in=u) - if not s: + user_answer = q.user_answers.filter(user__in=u).first() + if not user_answer: user_answers_marks[u].append(0) user_answers[u].append("") continue - ans = s[0].answer - if ans in q.answers.all().values_list("answer", flat=True): - a = 2 - elif ans in q.half_mark_answers.all().values_list("answer", - flat=True): - a = 1 - else: - a = 0 + ans = user_answer.answer + answer_score = user_answer.get_answer_score() user_answers[u].append(ans) - user_answers_marks[u].append(a) - user_answers_and_marks[u].append((ans, a)) + user_answers_marks[u].append(answer_score) + user_answers_and_marks[u].append((ans, answer_score)) user_scores = {} for user in user_answers_marks: user_scores[user] = sum(user_answers_marks[user]) - # Users with answers - # - # for q in questions: - # answers = q.user_answers.all() - # - # for ans in answers: - # user = ans.user - # if ans.answer in q.answers.all().values_list("answer", flat=True): - # user_answers[user].append(2) - # - total = len(questions) return render( @@ -706,3 +698,31 @@ def exam_scores(request, pk): "user_answers_and_marks": user_answers_and_marks, }, ) + +def cid_scores(request, pk): + #exam = get_object_or_404(Exam, pk=pk) + + # TODO:Need some kind of test for cid + cid = pk + + #questions = exam.exam_questions.all() + answers = CidUserAnswer.objects.filter( + cid=cid) + + + if not answers: + return Http404("cid not found") + + exam_ids = answers.values_list("exam").distinct() + + exams = Exam.objects.filter(id__in=exam_ids) + + + return render( + request, + "anatomy/cid_scores.html", + { + "exams": exams, + "cid": cid, + }, + ) \ No newline at end of file