start combining answers
This commit is contained in:
+12
-14
@@ -3,9 +3,7 @@ from .models import (
|
|||||||
AnatomyQuestion,
|
AnatomyQuestion,
|
||||||
Examination,
|
Examination,
|
||||||
QuestionType,
|
QuestionType,
|
||||||
Answers,
|
Answer,
|
||||||
HalfMarkAnswers,
|
|
||||||
IncorrectAnswers,
|
|
||||||
CidUserAnswer,
|
CidUserAnswer,
|
||||||
Exam,
|
Exam,
|
||||||
Modality,
|
Modality,
|
||||||
@@ -17,18 +15,18 @@ from reversion.admin import VersionAdmin
|
|||||||
|
|
||||||
# Register your models here.
|
# Register your models here.
|
||||||
class AnatomyAnswersInline(admin.TabularInline):
|
class AnatomyAnswersInline(admin.TabularInline):
|
||||||
model = Answers
|
model = Answer
|
||||||
extra = 1
|
extra = 1
|
||||||
|
|
||||||
|
|
||||||
class HalfMarkAnatomyAnswersInline(admin.TabularInline):
|
#class HalfMarkAnatomyAnswersInline(admin.TabularInline):
|
||||||
model = HalfMarkAnswers
|
# model = HalfMarkAnswers
|
||||||
extra = 1
|
# extra = 1
|
||||||
|
#
|
||||||
|
#
|
||||||
class IncorrectAnatomyAnswersInline(admin.TabularInline):
|
#class IncorrectAnatomyAnswersInline(admin.TabularInline):
|
||||||
model = IncorrectAnswers
|
# model = IncorrectAnswers
|
||||||
extra = 1
|
# extra = 1
|
||||||
|
|
||||||
|
|
||||||
class ExamInline(admin.TabularInline):
|
class ExamInline(admin.TabularInline):
|
||||||
@@ -39,8 +37,8 @@ class ExamInline(admin.TabularInline):
|
|||||||
class AnatomyAdmin(VersionAdmin):
|
class AnatomyAdmin(VersionAdmin):
|
||||||
inlines = [
|
inlines = [
|
||||||
AnatomyAnswersInline,
|
AnatomyAnswersInline,
|
||||||
HalfMarkAnatomyAnswersInline,
|
#HalfMarkAnatomyAnswersInline,
|
||||||
IncorrectAnatomyAnswersInline,
|
#IncorrectAnatomyAnswersInline,
|
||||||
ExamInline,
|
ExamInline,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
+50
-30
@@ -74,10 +74,12 @@ class AnatomyQuestion(models.Model):
|
|||||||
|
|
||||||
examination = models.ForeignKey(Examination,
|
examination = models.ForeignKey(Examination,
|
||||||
on_delete=models.SET_NULL,
|
on_delete=models.SET_NULL,
|
||||||
null=True, blank=True)
|
null=True,
|
||||||
|
blank=True)
|
||||||
modality = models.ForeignKey(Modality,
|
modality = models.ForeignKey(Modality,
|
||||||
on_delete=models.SET_NULL,
|
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,
|
body_part = models.ForeignKey(BodyPart,
|
||||||
on_delete=models.SET_NULL,
|
on_delete=models.SET_NULL,
|
||||||
null=True,
|
null=True,
|
||||||
@@ -107,16 +109,19 @@ class AnatomyQuestion(models.Model):
|
|||||||
|
|
||||||
if not unmarked_answers:
|
if not unmarked_answers:
|
||||||
return "No answers to mark"
|
return "No answers to mark"
|
||||||
return format_html("<span class='warn'>{} answer unmarked:</span> {}".format(len(unmarked_answers),
|
return format_html(
|
||||||
", ".join(unmarked_answers)))
|
"<span class='warn'>{} answer unmarked:</span> {}".format(
|
||||||
|
len(unmarked_answers), ", ".join(unmarked_answers)))
|
||||||
|
|
||||||
def GetUnmarkedAnswers(self):
|
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()
|
unmarked_answers = user_answers - self.GetMarkedAnswers()
|
||||||
|
|
||||||
return unmarked_answers
|
return unmarked_answers
|
||||||
|
|
||||||
def GetMarkedAnswers(self):
|
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()])
|
correct_answers = set([i.answer.lower() for i in self.answers.all()])
|
||||||
half_mark_answers = set(
|
half_mark_answers = set(
|
||||||
[i.answer.lower() for i in self.half_mark_answers.all()])
|
[i.answer.lower() for i in self.half_mark_answers.all()])
|
||||||
@@ -127,25 +132,19 @@ class AnatomyQuestion(models.Model):
|
|||||||
return marked_answers
|
return marked_answers
|
||||||
|
|
||||||
|
|
||||||
class Answers(models.Model):
|
class Answer(models.Model):
|
||||||
question = models.ForeignKey(AnatomyQuestion,
|
question = models.ForeignKey(AnatomyQuestion,
|
||||||
related_name="answers",
|
related_name="answers",
|
||||||
on_delete=models.CASCADE)
|
on_delete=models.CASCADE)
|
||||||
answer = models.CharField(max_length=500)
|
answer = models.CharField(max_length=500)
|
||||||
|
|
||||||
def __str__(self):
|
class MarkOptions(models.TextChoices):
|
||||||
return self.answer
|
UNMARKED = '', _('Unmarked')
|
||||||
|
INCORRECT = '0', _('Incorrect')
|
||||||
|
HALF_MARK = '1', _('Half mark')
|
||||||
|
CORRECT = '2', _('Correct')
|
||||||
|
|
||||||
def clean(self):
|
status = models.CharField(max_length=1, choices=MarkOptions.choices, default=MarkOptions.UNMARKED)
|
||||||
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):
|
def __str__(self):
|
||||||
return self.answer
|
return self.answer
|
||||||
@@ -154,19 +153,36 @@ class HalfMarkAnswers(models.Model):
|
|||||||
if self.answer:
|
if self.answer:
|
||||||
self.answer.strip()
|
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):
|
#class HalfMarkAnswers(models.Model):
|
||||||
return self.answer
|
# question = models.ForeignKey(AnatomyQuestion,
|
||||||
|
# related_name="half_mark_answers",
|
||||||
def clean(self):
|
# on_delete=models.CASCADE)
|
||||||
if self.answer:
|
# answer = models.CharField(max_length=500)
|
||||||
self.answer.strip()
|
#
|
||||||
|
# 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):
|
class Exam(models.Model):
|
||||||
@@ -174,7 +190,8 @@ class Exam(models.Model):
|
|||||||
exam_questions = models.ManyToManyField(AnatomyQuestion,
|
exam_questions = models.ManyToManyField(AnatomyQuestion,
|
||||||
related_name="exams")
|
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):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
@@ -251,3 +268,6 @@ class CidUserAnswer(models.Model):
|
|||||||
def clean(self):
|
def clean(self):
|
||||||
if self.answer:
|
if self.answer:
|
||||||
self.answer.strip()
|
self.answer.strip()
|
||||||
|
|
||||||
|
def get_compare_string(self):
|
||||||
|
return self.answer.lower()
|
||||||
+44
-25
@@ -16,9 +16,9 @@ from .models import (
|
|||||||
CidUserAnswer,
|
CidUserAnswer,
|
||||||
UserAnswer,
|
UserAnswer,
|
||||||
Exam,
|
Exam,
|
||||||
Answers,
|
Answer,
|
||||||
HalfMarkAnswers,
|
#HalfMarkAnswers,
|
||||||
IncorrectAnswers,
|
#IncorrectAnswers,
|
||||||
)
|
)
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
@@ -235,14 +235,13 @@ def loadJsonAnswer(answer):
|
|||||||
|
|
||||||
if not exam.active:
|
if not exam.active:
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
"success":
|
"success": False,
|
||||||
False,
|
"error": "No active exam: {}".format(answer["eid"])
|
||||||
"error":
|
|
||||||
"No active exam: {}".format(answer["eid"])
|
|
||||||
})
|
})
|
||||||
|
|
||||||
exiting_answers = CidUserAnswer.objects.filter(
|
exiting_answers = CidUserAnswer.objects.filter(question__id=answer["qid"],
|
||||||
question__id=answer["qid"], exam__id=answer["eid"], cid=answer["cid"])
|
exam__id=answer["eid"],
|
||||||
|
cid=answer["cid"])
|
||||||
|
|
||||||
if not exiting_answers:
|
if not exiting_answers:
|
||||||
ans = CidUserAnswer(answer=answer["ans"], cid=answer["cid"])
|
ans = CidUserAnswer(answer=answer["ans"], cid=answer["cid"])
|
||||||
@@ -311,18 +310,35 @@ def mark(request, pk, sk):
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
raise Http404("Exam question does not exist")
|
raise Http404("Exam question does not exist")
|
||||||
|
|
||||||
correct_answers = [i.answer.lower() for i in question.answers.all()]
|
answers_dict = {}
|
||||||
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()]
|
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":
|
if request.method == "POST":
|
||||||
|
|
||||||
form = MarkAnatomyQuestionForm(request.POST)
|
form = MarkAnatomyQuestionForm(request.POST)
|
||||||
|
# *******************************
|
||||||
|
# TODO: convert to JSON request
|
||||||
|
# *******************************
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
cd = form.cleaned_data
|
cd = form.cleaned_data
|
||||||
# correct = cd.get("correct")
|
# correct = cd.get("correct")
|
||||||
@@ -389,23 +405,25 @@ def mark(request, pk, sk):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def active_exams(request):
|
def active_exams(request):
|
||||||
exams = Exam.objects.all()
|
exams = Exam.objects.all()
|
||||||
print(exams)
|
print(exams)
|
||||||
|
|
||||||
active_exams = {
|
active_exams = {"exams": []}
|
||||||
"exams" : []
|
|
||||||
}
|
|
||||||
|
|
||||||
for exam in exams:
|
for exam in exams:
|
||||||
if exam.active:
|
if exam.active:
|
||||||
active_exams["exams"].append({
|
active_exams["exams"].append({
|
||||||
"name": exam.get_exam_name(),
|
"name":
|
||||||
"url": request.build_absolute_uri(exam.get_json_url()),
|
exam.get_exam_name(),
|
||||||
|
"url":
|
||||||
|
request.build_absolute_uri(exam.get_json_url()),
|
||||||
})
|
})
|
||||||
|
|
||||||
return JsonResponse(active_exams)
|
return JsonResponse(active_exams)
|
||||||
|
|
||||||
|
|
||||||
def exam_json(request, pk):
|
def exam_json(request, pk):
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
exam = get_object_or_404(Exam, pk=pk)
|
||||||
|
|
||||||
@@ -462,10 +480,11 @@ def exam_scores_cid(request, pk):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
ans = s[0].answer
|
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"),
|
||||||
a = 2
|
|
||||||
elif ans.lower() in q.half_mark_answers.all().values_list(Lower("answer"),
|
|
||||||
flat=True):
|
flat=True):
|
||||||
|
a = 2
|
||||||
|
elif ans.lower() in q.half_mark_answers.all().values_list(
|
||||||
|
Lower("answer"), flat=True):
|
||||||
a = 1
|
a = 1
|
||||||
else:
|
else:
|
||||||
a = 0
|
a = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user