.
This commit is contained in:
+2
-1
@@ -1,5 +1,5 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from .models import Long, LongSeries, LongSeriesImage, Note, LongCreationDefault, Exam
|
from .models import Long, LongSeries, LongSeriesImage, Note, LongCreationDefault, Exam, CidUserAnswer
|
||||||
|
|
||||||
import tagulous.admin
|
import tagulous.admin
|
||||||
|
|
||||||
@@ -20,6 +20,7 @@ admin.site.register(Note)
|
|||||||
admin.site.register(LongCreationDefault)
|
admin.site.register(LongCreationDefault)
|
||||||
admin.site.register(LongSeries)
|
admin.site.register(LongSeries)
|
||||||
admin.site.register(LongSeriesImage)
|
admin.site.register(LongSeriesImage)
|
||||||
|
admin.site.register(CidUserAnswer)
|
||||||
|
|
||||||
|
|
||||||
class LongImageInline(admin.TabularInline):
|
class LongImageInline(admin.TabularInline):
|
||||||
|
|||||||
+21
-42
@@ -143,6 +143,14 @@ class Long(models.Model):
|
|||||||
["http://penracourses.org.uk{}".format(i.url) for i in self.GetImages()]
|
["http://penracourses.org.uk{}".format(i.url) for i in self.GetImages()]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def GetUnmarkedAnswerCount(self):
|
||||||
|
answers = self.cid_user_answers.all()
|
||||||
|
return len([ans for ans in answers if not ans.is_marked()])
|
||||||
|
|
||||||
|
def GetUnmarkedAnswers(self):
|
||||||
|
answers = self.cid_user_answers.all()
|
||||||
|
return [ans for ans in answers if not ans.is_marked()]
|
||||||
|
|
||||||
# def GetNonFeedbackQuestionImages(self):
|
# def GetNonFeedbackQuestionImages(self):
|
||||||
# return self.GetImages()
|
# return self.GetImages()
|
||||||
|
|
||||||
@@ -408,7 +416,7 @@ class CidUserAnswer(models.Model):
|
|||||||
EIGHT = "8", _("8")
|
EIGHT = "8", _("8")
|
||||||
|
|
||||||
score = models.CharField(
|
score = models.CharField(
|
||||||
max_length=3, choices=ScoreOptions.choices, default=ScoreOptions.UNMARKED
|
max_length=3, choices=ScoreOptions.choices, default=ScoreOptions.UNMARKED, blank=True
|
||||||
)
|
)
|
||||||
|
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
@@ -419,8 +427,8 @@ class CidUserAnswer(models.Model):
|
|||||||
exam = self.exam
|
exam = self.exam
|
||||||
except (Exam.DoesNotExist, KeyError) as e:
|
except (Exam.DoesNotExist, KeyError) as e:
|
||||||
exam = "None"
|
exam = "None"
|
||||||
return "{}/{}/{}: {}".format(
|
return "{}/{}/{} ({})".format(
|
||||||
exam, self.cid, self.question.GetPrimaryAnswer(), self.answer
|
exam, self.cid, self.created, self.updated
|
||||||
)
|
)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
@@ -428,13 +436,10 @@ class CidUserAnswer(models.Model):
|
|||||||
return super(CidUserAnswer, self).save(*args, **kwargs)
|
return super(CidUserAnswer, self).save(*args, **kwargs)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if self.answer:
|
for ans in (self.answer_observations, self.answer_interpretation, self.answer_principle_diagnosis, self.answer_differential_diagnosis, self.answer_management):
|
||||||
self.answer = self.answer.strip()
|
if ans:
|
||||||
|
ans = ans.strip()
|
||||||
|
|
||||||
s = self.answer.lower()
|
|
||||||
s = s.translate(str.maketrans("", "", string.punctuation))
|
|
||||||
|
|
||||||
self.answer_compare = s
|
|
||||||
|
|
||||||
# def get_compare_string(self):
|
# def get_compare_string(self):
|
||||||
# # strip here should be unneccasry (providing clean is now working)
|
# # strip here should be unneccasry (providing clean is now working)
|
||||||
@@ -442,37 +447,11 @@ class CidUserAnswer(models.Model):
|
|||||||
# s = s.translate(str.maketrans('', '', string.punctuation))
|
# s = s.translate(str.maketrans('', '', string.punctuation))
|
||||||
# return s
|
# return s
|
||||||
|
|
||||||
def get_answer_score(self):
|
def is_marked(self):
|
||||||
q = self.question
|
if self.score == "":
|
||||||
|
return False
|
||||||
# First step we check that the normal/abnormal states match
|
|
||||||
if q.normal != self.normal:
|
|
||||||
# If they don't match the answer is wrong (score is 0)
|
|
||||||
return 0
|
|
||||||
# If both are normal full marks
|
|
||||||
elif q.normal and self.normal:
|
|
||||||
return 2
|
|
||||||
|
|
||||||
# Then compare answer strings (as per anatomy questions)
|
|
||||||
ans = self.answer_compare
|
|
||||||
if (
|
|
||||||
q.answers.filter(
|
|
||||||
answer_compare__iexact=ans, status=Answer.MarkOptions.CORRECT
|
|
||||||
).first()
|
|
||||||
is not None
|
|
||||||
):
|
|
||||||
mark = 2
|
|
||||||
elif (
|
|
||||||
q.answers.filter(
|
|
||||||
answer_compare__iexact=ans, status=Answer.MarkOptions.HALF_MARK
|
|
||||||
).first()
|
|
||||||
is not None
|
|
||||||
):
|
|
||||||
mark = 1
|
|
||||||
elif q.answers.filter(
|
|
||||||
answer_compare__iexact=ans, status=Answer.MarkOptions.INCORRECT
|
|
||||||
).first():
|
|
||||||
mark = 0
|
|
||||||
else:
|
else:
|
||||||
mark = "unmarked"
|
return True
|
||||||
return mark
|
|
||||||
|
def get_answer_score(self):
|
||||||
|
return self.score
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<ul id="question-mark-list">
|
<ul id="question-mark-list">
|
||||||
{% for question in questions.all %}
|
{% for question in questions.all %}
|
||||||
<li data-markcount={{question.GetUnmarkedAnswerCount}}><a href="{% url 'longs:mark' pk=exam.pk sk=forloop.counter0 %}">Question {{forloop.counter }}:
|
<li data-markcount={{question.GetUnmarkedAnswerCount}}><a href="{% url 'longs:mark' pk=exam.pk sk=forloop.counter0 %}">Question {{forloop.counter }}:
|
||||||
{{ question }}</a><br /> {{ question.GetUnmarkedAnswersString }}</li>
|
{{ question }}</a><br /> Answers to mark: {{question.GetUnmarkedAnswerCount}}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+20
-13
@@ -619,30 +619,37 @@ def loadJsonAnswer(answer):
|
|||||||
|
|
||||||
posted_answer = answer["ans"]
|
posted_answer = answer["ans"]
|
||||||
|
|
||||||
# Normal answers are just posted with the answer "Normal"
|
# Long cases seperate sections by qidn
|
||||||
normal = False
|
qidn = answer["qidn"]
|
||||||
if posted_answer == "Normal":
|
|
||||||
normal = True
|
|
||||||
posted_answer = ""
|
|
||||||
# We can ignore the first ab
|
|
||||||
elif answer["qidn"] == "1" and posted_answer == "Abnormal":
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
|
# If the user answer does not exist
|
||||||
if not exiting_answers:
|
if not exiting_answers:
|
||||||
ans = CidUserAnswer(answer=posted_answer, normal=normal, cid=answer["cid"])
|
ans = CidUserAnswer(cid=answer["cid"])
|
||||||
ans.question_id = answer["qid"]
|
ans.question_id = answer["qid"]
|
||||||
ans.exam_id = eid
|
ans.exam_id = eid
|
||||||
|
|
||||||
ans.full_clean()
|
|
||||||
|
|
||||||
ans.save()
|
# If the answer already exists or we have started populating it
|
||||||
else:
|
else:
|
||||||
# Update an existing answer
|
# Update an existing answer
|
||||||
# should never be more than one (famous last words)
|
# should never be more than one (famous last words)
|
||||||
ans = exiting_answers[0]
|
ans = exiting_answers[0]
|
||||||
ans.normal = normal
|
|
||||||
ans.answer = posted_answer
|
if qidn == "1":
|
||||||
|
ans.answer_observations = posted_answer
|
||||||
|
elif qidn == "2":
|
||||||
|
ans.answer_interpretation = posted_answer
|
||||||
|
elif qidn == "3":
|
||||||
|
ans.answer_principle_diagnosis = posted_answer
|
||||||
|
elif qidn == "4":
|
||||||
|
ans.answer_differential_diagnosis = posted_answer
|
||||||
|
elif qidn == "5":
|
||||||
|
ans.answer_management = posted_answer
|
||||||
|
|
||||||
|
# Mark as unmarked
|
||||||
|
ans.score = ans.ScoreOptions.UNMARKED
|
||||||
|
|
||||||
ans.full_clean()
|
ans.full_clean()
|
||||||
ans.save()
|
ans.save()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user