try to improve the scores pages

This commit is contained in:
Ross
2026-07-06 12:33:30 +01:00
parent 7bd1475daf
commit 50b80fd0c7
12 changed files with 287 additions and 250 deletions
+89 -37
View File
@@ -141,7 +141,30 @@ class Answer(models.Model):
def save(self, *args, **kwargs):
self.clean()
return super(Answer, self).save(*args, **kwargs)
res = super(Answer, self).save(*args, **kwargs)
# Update matching UserAnswer objects in real-time
status = self.status
callstate = UserAnswer.CallStateOptions.INCORRECTCALL
if status == Answer.MarkOptions.CORRECT:
callstate = UserAnswer.CallStateOptions.CORRECT
elif status == Answer.MarkOptions.HALF_MARK:
callstate = UserAnswer.CallStateOptions.PARTIALCALL
UserAnswer.objects.filter(
question=self.question,
normal=False,
answer_compare__iexact=self.answer_compare
).update(score=status, callstate=callstate)
return res
def delete(self, *args, **kwargs):
# Update matching UserAnswer objects back to UNMARKED in real-time
UserAnswer.objects.filter(
question=self.question,
normal=False,
answer_compare__iexact=self.answer_compare
).update(score=Answer.MarkOptions.UNMARKED, callstate=None)
return super(Answer, self).delete(*args, **kwargs)
def clean(self):
if self.answer:
@@ -823,10 +846,38 @@ class UserAnswer(UserAnswerBase):
def save(self, *args, **kwargs):
self.clean()
# Auto-mark on save based on existing template answers
q = self.question
if q.normal != self.normal:
self.callstate = UserAnswer.CallStateOptions.OVERCALL if q.normal else UserAnswer.CallStateOptions.UNDERCALL
self.score = Answer.MarkOptions.INCORRECT
elif q.normal and self.normal:
self.callstate = UserAnswer.CallStateOptions.CORRECT
self.score = Answer.MarkOptions.CORRECT
else:
ans = self.answer_compare
if ans == "":
self.score = Answer.MarkOptions.INCORRECT
self.callstate = UserAnswer.CallStateOptions.INCORRECTCALL
else:
marked_ans = Answer.objects.filter(question_id=self.question_id, answer_compare__iexact=ans).first()
if marked_ans is not None:
self.score = marked_ans.status
if marked_ans.status == Answer.MarkOptions.CORRECT:
self.callstate = UserAnswer.CallStateOptions.CORRECT
elif marked_ans.status == Answer.MarkOptions.HALF_MARK:
self.callstate = UserAnswer.CallStateOptions.PARTIALCALL
elif marked_ans.status == Answer.MarkOptions.INCORRECT:
self.callstate = UserAnswer.CallStateOptions.INCORRECTCALL
else:
self.score = Answer.MarkOptions.UNMARKED
self.callstate = None
return super(UserAnswer, self).save(*args, **kwargs)
def clean(self):
self.score = Answer.MarkOptions.UNMARKED
if not self.score:
self.score = Answer.MarkOptions.UNMARKED
if self.answer:
self.answer = self.answer.strip()
self.answer_compare = get_answer_compare(self.answer)
@@ -855,66 +906,67 @@ class UserAnswer(UserAnswerBase):
return self.callstate
def get_answer_score(self, cached=True):
if cached and self.score:
print("CACHED")
if cached and self.score and self.score != Answer.MarkOptions.UNMARKED:
if self.score == Answer.MarkOptions.CORRECT:
mark = 2
return 2
elif self.score == Answer.MarkOptions.HALF_MARK:
mark = 1
return 1
elif self.score == Answer.MarkOptions.INCORRECT:
mark = 0
return mark
print("NOT CACHED")
return 0
q = self.question
# First step we check that the normal/abnormal states match
if q.normal != self.normal:
if q.normal:
self.callstate = UserAnswer.CallStateOptions.OVERCALL
else:
self.callstate = UserAnswer.CallStateOptions.UNDERCALL
self.score = Answer.MarkOptions.INCORRECT
self.save()
# If they don't match the answer is wrong (score is 0)
new_callstate = UserAnswer.CallStateOptions.OVERCALL if q.normal else UserAnswer.CallStateOptions.UNDERCALL
if self.score != Answer.MarkOptions.INCORRECT or self.callstate != new_callstate:
self.score = Answer.MarkOptions.INCORRECT
self.callstate = new_callstate
self.save()
return 0
# If both are normal full marks
elif q.normal and self.normal:
self.callstate = UserAnswer.CallStateOptions.CORRECT
self.score = Answer.MarkOptions.CORRECT
self.save()
if self.score != Answer.MarkOptions.CORRECT or self.callstate != UserAnswer.CallStateOptions.CORRECT:
self.score = Answer.MarkOptions.CORRECT
self.callstate = UserAnswer.CallStateOptions.CORRECT
self.save()
return 2
# Then compare answer strings (as per anatomy questions)
ans = self.answer_compare
if ans == "":
self.score == Answer.MarkOptions.INCORRECT
self.save()
if self.score != Answer.MarkOptions.INCORRECT or self.callstate != UserAnswer.CallStateOptions.INCORRECTCALL:
self.score = Answer.MarkOptions.INCORRECT
self.callstate = UserAnswer.CallStateOptions.INCORRECTCALL
self.save()
return 0
# TODO: this should be cleaned up as we don't want duplicates...
# try:
# marked_ans = q.answers.get(answer_compare__iexact=ans)
# except Answer.DoesNotExist:
# marked_ans = None
marked_ans = q.answers.filter(answer_compare__iexact=ans).first()
marked_ans = None
for a in q.answers.all():
if a.answer_compare.lower() == ans.lower():
marked_ans = a
break
mark = "unmarked"
if marked_ans is not None:
self.score = marked_ans.status
new_callstate = UserAnswer.CallStateOptions.INCORRECTCALL
if marked_ans.status == Answer.MarkOptions.CORRECT:
self.callstate = UserAnswer.CallStateOptions.CORRECT
new_callstate = UserAnswer.CallStateOptions.CORRECT
mark = 2
elif marked_ans.status == Answer.MarkOptions.HALF_MARK:
self.callstate = UserAnswer.CallStateOptions.PARTIALCALL
new_callstate = UserAnswer.CallStateOptions.PARTIALCALL
mark = 1
elif marked_ans.status == Answer.MarkOptions.INCORRECT:
self.callstate = UserAnswer.CallStateOptions.INCORRECTCALL
new_callstate = UserAnswer.CallStateOptions.INCORRECTCALL
mark = 0
self.save()
if self.score != marked_ans.status or self.callstate != new_callstate:
self.score = marked_ans.status
self.callstate = new_callstate
self.save()
else:
if self.score != Answer.MarkOptions.UNMARKED or self.callstate is not None:
self.score = Answer.MarkOptions.UNMARKED
self.callstate = None
self.save()
return mark