diff --git a/anatomy/admin.py b/anatomy/admin.py index 42435a49..a203e573 100644 --- a/anatomy/admin.py +++ b/anatomy/admin.py @@ -3,9 +3,7 @@ from .models import ( AnatomyQuestion, Examination, QuestionType, - Answers, - HalfMarkAnswers, - IncorrectAnswers, + Answer, CidUserAnswer, Exam, Modality, @@ -17,18 +15,18 @@ from reversion.admin import VersionAdmin # Register your models here. class AnatomyAnswersInline(admin.TabularInline): - model = Answers + model = Answer extra = 1 -class HalfMarkAnatomyAnswersInline(admin.TabularInline): - model = HalfMarkAnswers - extra = 1 - - -class IncorrectAnatomyAnswersInline(admin.TabularInline): - model = IncorrectAnswers - extra = 1 +#class HalfMarkAnatomyAnswersInline(admin.TabularInline): +# model = HalfMarkAnswers +# extra = 1 +# +# +#class IncorrectAnatomyAnswersInline(admin.TabularInline): +# model = IncorrectAnswers +# extra = 1 class ExamInline(admin.TabularInline): @@ -39,8 +37,8 @@ class ExamInline(admin.TabularInline): class AnatomyAdmin(VersionAdmin): inlines = [ AnatomyAnswersInline, - HalfMarkAnatomyAnswersInline, - IncorrectAnatomyAnswersInline, + #HalfMarkAnatomyAnswersInline, + #IncorrectAnatomyAnswersInline, ExamInline, ] diff --git a/anatomy/models.py b/anatomy/models.py index 1713a306..026f023f 100644 --- a/anatomy/models.py +++ b/anatomy/models.py @@ -74,10 +74,12 @@ class AnatomyQuestion(models.Model): examination = models.ForeignKey(Examination, on_delete=models.SET_NULL, - null=True, blank=True) + null=True, + blank=True) modality = models.ForeignKey(Modality, on_delete=models.SET_NULL, - null=True, help_text="Modality of the image") + null=True, + help_text="Modality of the image") body_part = models.ForeignKey(BodyPart, on_delete=models.SET_NULL, null=True, @@ -107,16 +109,19 @@ class AnatomyQuestion(models.Model): if not unmarked_answers: return "No answers to mark" - return format_html("{} answer unmarked: {}".format(len(unmarked_answers), - ", ".join(unmarked_answers))) + return format_html( + "{} answer unmarked: {}".format( + len(unmarked_answers), ", ".join(unmarked_answers))) def GetUnmarkedAnswers(self): - user_answers = set([i.answer.lower() for i in self.cid_user_answers.all()]) + user_answers = set( + [i.get_compare_string() for i in self.cid_user_answers.all()]) unmarked_answers = user_answers - self.GetMarkedAnswers() return unmarked_answers 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()]) half_mark_answers = set( [i.answer.lower() for i in self.half_mark_answers.all()]) @@ -127,25 +132,19 @@ class AnatomyQuestion(models.Model): return marked_answers -class Answers(models.Model): +class Answer(models.Model): question = models.ForeignKey(AnatomyQuestion, related_name="answers", on_delete=models.CASCADE) answer = models.CharField(max_length=500) - def __str__(self): - return self.answer + class MarkOptions(models.TextChoices): + UNMARKED = '', _('Unmarked') + INCORRECT = '0', _('Incorrect') + HALF_MARK = '1', _('Half mark') + CORRECT = '2', _('Correct') - def clean(self): - if self.answer: - self.answer.strip() - - -class HalfMarkAnswers(models.Model): - question = models.ForeignKey(AnatomyQuestion, - related_name="half_mark_answers", - on_delete=models.CASCADE) - answer = models.CharField(max_length=500) + status = models.CharField(max_length=1, choices=MarkOptions.choices, default=MarkOptions.UNMARKED) def __str__(self): return self.answer @@ -154,19 +153,36 @@ class HalfMarkAnswers(models.Model): if self.answer: self.answer.strip() + def get_compare_string(self): + return self.answer.lower() -class IncorrectAnswers(models.Model): - question = models.ForeignKey(AnatomyQuestion, - related_name="incorrect_answers", - on_delete=models.CASCADE) - answer = models.CharField(max_length=500) - def __str__(self): - return self.answer - - def clean(self): - if self.answer: - self.answer.strip() +#class HalfMarkAnswers(models.Model): +# question = models.ForeignKey(AnatomyQuestion, +# related_name="half_mark_answers", +# on_delete=models.CASCADE) +# answer = models.CharField(max_length=500) +# +# def __str__(self): +# return self.answer +# +# def clean(self): +# if self.answer: +# self.answer.strip() +# +# +#class IncorrectAnswers(models.Model): +# question = models.ForeignKey(AnatomyQuestion, +# related_name="incorrect_answers", +# on_delete=models.CASCADE) +# answer = models.CharField(max_length=500) +# +# def __str__(self): +# return self.answer +# +# def clean(self): +# if self.answer: +# self.answer.strip() class Exam(models.Model): @@ -174,7 +190,8 @@ class Exam(models.Model): exam_questions = models.ManyToManyField(AnatomyQuestion, related_name="exams") - active = models.BooleanField(help_text="If an exam should be available", default=True) + active = models.BooleanField(help_text="If an exam should be available", + default=True) def __str__(self): return self.name @@ -183,7 +200,7 @@ class Exam(models.Model): return self.name def get_json_url(self): - return reverse('anatomy:exam_json', args=(self.pk,)) + return reverse('anatomy:exam_json', args=(self.pk, )) class UserAnswer(models.Model): @@ -251,3 +268,6 @@ class CidUserAnswer(models.Model): def clean(self): if self.answer: self.answer.strip() + + def get_compare_string(self): + return self.answer.lower() \ No newline at end of file diff --git a/anatomy/views.py b/anatomy/views.py index 3e5bb1a6..3fedb2d4 100644 --- a/anatomy/views.py +++ b/anatomy/views.py @@ -16,9 +16,9 @@ from .models import ( CidUserAnswer, UserAnswer, Exam, - Answers, - HalfMarkAnswers, - IncorrectAnswers, + Answer, + #HalfMarkAnswers, + #IncorrectAnswers, ) from collections import defaultdict @@ -222,8 +222,8 @@ def flag_question(request): def loadJsonAnswer(answer): # As access is not restricted make sure the data appears valid if (not isinstance(answer["cid"], - int)) or (not isinstance(answer["eid"], int) or - (not isinstance(answer["ans"], str))): + int)) or (not isinstance(answer["eid"], int) or + (not isinstance(answer["ans"], str))): return JsonResponse({"success": False}) # The model should catch invalid data but this should be less intensive @@ -235,14 +235,13 @@ def loadJsonAnswer(answer): if not exam.active: return JsonResponse({ - "success": - False, - "error": - "No active exam: {}".format(answer["eid"]) + "success": False, + "error": "No active exam: {}".format(answer["eid"]) }) - exiting_answers = CidUserAnswer.objects.filter( - question__id=answer["qid"], exam__id=answer["eid"], cid=answer["cid"]) + exiting_answers = CidUserAnswer.objects.filter(question__id=answer["qid"], + exam__id=answer["eid"], + cid=answer["cid"]) if not exiting_answers: ans = CidUserAnswer(answer=answer["ans"], cid=answer["cid"]) @@ -311,18 +310,35 @@ def mark(request, pk, sk): except IndexError: raise Http404("Exam question does not exist") - correct_answers = [i.answer.lower() for i in question.answers.all()] - half_correct_answers = [i.answer.lower() for i in question.half_mark_answers.all()] - incorrect_answers = [i.answer.lower() for i in question.incorrect_answers.all()] + answers_dict = {} + + for ans in question.answer.all(): + answers_dict[ans.get_compare_string()] = ans + + marked_answers_set = set(answers_dict.keys()) + + #correct_answers = [i.answer.lower() for i in question.answers.all()] + #half_correct_answers = [ + # i.answer.lower() for i in question.half_mark_answers.all() + #] + #incorrect_answers = [ + # i.answer.lower() for i in question.incorrect_answers.all() + #] + + # It's probably better to do some processing/checking in the model + user_answers = (set([ + i.answer.lower() + for i in question.cid_user_answers.all() if i.strip() != "" + ]) - marked_answers_set) # .filter(user=User) + + - user_answers = (set([i.answer.lower() for i in question.cid_user_answers.all()]) - - set(correct_answers) - set(half_correct_answers) - - set(incorrect_answers)) # .filter(user=User) - user_answers = set([i for i in user_answers if i.strip() != ""]) if request.method == "POST": form = MarkAnatomyQuestionForm(request.POST) - + # ******************************* + # TODO: convert to JSON request + # ******************************* if form.is_valid(): cd = form.cleaned_data # correct = cd.get("correct") @@ -389,23 +405,25 @@ def mark(request, pk, sk): }, ) + def active_exams(request): exams = Exam.objects.all() print(exams) - active_exams = { - "exams" : [] - } + active_exams = {"exams": []} for exam in exams: if exam.active: active_exams["exams"].append({ - "name": exam.get_exam_name(), - "url": request.build_absolute_uri(exam.get_json_url()), + "name": + exam.get_exam_name(), + "url": + request.build_absolute_uri(exam.get_json_url()), }) return JsonResponse(active_exams) + def exam_json(request, pk): exam = get_object_or_404(Exam, pk=pk) @@ -462,10 +480,11 @@ def exam_scores_cid(request, pk): continue ans = s[0].answer - if ans.lower() in q.answers.all().values_list(Lower("answer"), flat=True): + if ans.lower() in q.answers.all().values_list(Lower("answer"), + flat=True): a = 2 - elif ans.lower() in q.half_mark_answers.all().values_list(Lower("answer"), - flat=True): + elif ans.lower() in q.half_mark_answers.all().values_list( + Lower("answer"), flat=True): a = 1 else: a = 0