further abstraction
This commit is contained in:
+2
-3
@@ -35,6 +35,7 @@ from generic.models import (
|
||||
CidUser,
|
||||
CidUserExam,
|
||||
CidUserGroup,
|
||||
ExamCollectionGenericBase,
|
||||
Examination,
|
||||
# Condition,
|
||||
ExamBase,
|
||||
@@ -404,7 +405,7 @@ class Series(SeriesBase):
|
||||
|
||||
|
||||
|
||||
class CaseCollection(models.Model):
|
||||
class CaseCollection(ExamCollectionGenericBase):
|
||||
app_name = "atlas"
|
||||
|
||||
name = models.CharField(max_length=255, unique=True)
|
||||
@@ -458,8 +459,6 @@ class CaseCollection(models.Model):
|
||||
# related_name="atlas_authored_cases",
|
||||
)
|
||||
|
||||
cid_users = GenericRelation("generic.CidUserExam")
|
||||
|
||||
valid_cid_users = models.ManyToManyField(
|
||||
CidUser, blank=True, related_name="casecollection_exams"
|
||||
)
|
||||
|
||||
+123
-112
@@ -310,126 +310,18 @@ class SeriesBase(models.Model):
|
||||
except pydicom.errors.InvalidDicomError:
|
||||
pass
|
||||
|
||||
class ExamBase(models.Model):
|
||||
name = models.CharField(max_length=200, help_text="Name of the exam")
|
||||
# exam_questions = SortedManyToManyField(Long, related_name="exams", blank="true")
|
||||
class ExamCollectionGenericBase(models.Model):
|
||||
"""Holds functions that relate to both case and other exams
|
||||
|
||||
active = models.BooleanField(
|
||||
help_text="If an exam should be available to take", default=False
|
||||
)
|
||||
|
||||
exam_mode = models.BooleanField(
|
||||
help_text="If an exam should be taken in exam mode (users results will be submited to the server for marking)",
|
||||
default=False,
|
||||
)
|
||||
|
||||
include_history = models.BooleanField(
|
||||
help_text="If an exam should include history when taking",
|
||||
default=False,
|
||||
)
|
||||
|
||||
publish_results = models.BooleanField(
|
||||
help_text="If an exams results should be available", default=False
|
||||
)
|
||||
|
||||
recreate_json = models.BooleanField(
|
||||
help_text="If the json cache needs updating", default=False
|
||||
)
|
||||
|
||||
json_creation_time = models.DateTimeField(blank=True, default=None, null=True)
|
||||
exam_json_id = models.IntegerField(
|
||||
default=1, help_text="auto incrementing field when json recreated"
|
||||
)
|
||||
|
||||
archive = models.BooleanField(
|
||||
help_text="Archived exams will remain on the test system but will not be displayed by default",
|
||||
default=False,
|
||||
)
|
||||
|
||||
open_access = models.BooleanField(
|
||||
help_text="If the exam is freely accessible (to view and edit on the test system)",
|
||||
default=False,
|
||||
)
|
||||
|
||||
authors_only = models.BooleanField(
|
||||
help_text="If true only exam authors will be able to view.",
|
||||
default=False,
|
||||
)
|
||||
|
||||
stats_mean = models.FloatField(default=0)
|
||||
stats_mode = models.CharField(default=0, max_length=25)
|
||||
stats_median = models.FloatField(default=0)
|
||||
|
||||
stats_candidates = models.FloatField(default=0)
|
||||
|
||||
stats_min = models.FloatField(default=0)
|
||||
stats_max = models.FloatField(default=0)
|
||||
|
||||
stats_max_possible = models.FloatField(default=0)
|
||||
|
||||
# stats_graph = models.TextField(default=0)
|
||||
|
||||
user_scores = models.JSONField(default=dict)
|
||||
e.g. user management
|
||||
|
||||
"""
|
||||
# Is this actually used?
|
||||
cid_users = GenericRelation("generic.CidUserExam")
|
||||
|
||||
exam_results_emailed = models.DateTimeField(default=None, null=True)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def save(self, *args, recreate_json=True, **kwargs):
|
||||
self.recreate_json = recreate_json
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def get_exam_stats(self, name=True):
|
||||
if self.stats_candidates < int(4):
|
||||
return f"- Candidates: {int(self.stats_candidates)} (too few to generate stats)"
|
||||
|
||||
text = f"""- Candidates: {int(self.stats_candidates)}
|
||||
- Mean: {self.stats_mean:.2f} Median: {self.stats_median} Mode: {self.stats_mode} [Min: {self.stats_min} / Max: {self.stats_max}]
|
||||
"""
|
||||
if name:
|
||||
text = f"""{self.name}
|
||||
{"-"*len(self.name)}
|
||||
{text}
|
||||
"""
|
||||
return text
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("{}:exam_overview".format(self.app_name), kwargs={"pk": self.pk})
|
||||
|
||||
def get_cid_edit_url(self):
|
||||
return reverse(
|
||||
"{}:exam_cids_edit".format(self.app_name), kwargs={"exam_id": self.pk}
|
||||
)
|
||||
|
||||
def get_user_edit_url(self):
|
||||
return reverse(
|
||||
"{}:exam_users_edit".format(self.app_name), kwargs={"exam_id": self.pk}
|
||||
)
|
||||
|
||||
def get_take_url(self):
|
||||
return f"{settings.REMOTE_URL}/rts"
|
||||
|
||||
def get_exam_name(self):
|
||||
return self.name
|
||||
|
||||
def get_json_url(self, cid=None, passcode=None):
|
||||
if cid is None:
|
||||
return reverse("{}:exam_json".format(self.app_name), args=(self.pk,))
|
||||
else:
|
||||
return reverse(
|
||||
"{}:exam_json_cid".format(self.app_name), args=(self.pk, cid, passcode)
|
||||
)
|
||||
|
||||
def get_question_index(self, question):
|
||||
return list(self.exam_questions.all()).index(question)
|
||||
|
||||
def get_authors(self):
|
||||
"""Returns a comma seperated text list of authors"""
|
||||
authors = ", ".join([i.username for i in self.author.all()])
|
||||
@@ -536,6 +428,125 @@ class ExamBase(models.Model):
|
||||
content_type=content_type, object_id=self.pk, user_user=user_user
|
||||
)
|
||||
|
||||
class ExamBase(ExamCollectionGenericBase):
|
||||
name = models.CharField(max_length=200, help_text="Name of the exam")
|
||||
# exam_questions = SortedManyToManyField(Long, related_name="exams", blank="true")
|
||||
|
||||
active = models.BooleanField(
|
||||
help_text="If an exam should be available to take", default=False
|
||||
)
|
||||
|
||||
exam_mode = models.BooleanField(
|
||||
help_text="If an exam should be taken in exam mode (users results will be submited to the server for marking)",
|
||||
default=False,
|
||||
)
|
||||
|
||||
include_history = models.BooleanField(
|
||||
help_text="If an exam should include history when taking",
|
||||
default=False,
|
||||
)
|
||||
|
||||
publish_results = models.BooleanField(
|
||||
help_text="If an exams results should be available", default=False
|
||||
)
|
||||
|
||||
recreate_json = models.BooleanField(
|
||||
help_text="If the json cache needs updating", default=False
|
||||
)
|
||||
|
||||
json_creation_time = models.DateTimeField(blank=True, default=None, null=True)
|
||||
exam_json_id = models.IntegerField(
|
||||
default=1, help_text="auto incrementing field when json recreated"
|
||||
)
|
||||
|
||||
archive = models.BooleanField(
|
||||
help_text="Archived exams will remain on the test system but will not be displayed by default",
|
||||
default=False,
|
||||
)
|
||||
|
||||
open_access = models.BooleanField(
|
||||
help_text="If the exam is freely accessible (to view and edit on the test system)",
|
||||
default=False,
|
||||
)
|
||||
|
||||
authors_only = models.BooleanField(
|
||||
help_text="If true only exam authors will be able to view.",
|
||||
default=False,
|
||||
)
|
||||
|
||||
stats_mean = models.FloatField(default=0)
|
||||
stats_mode = models.CharField(default=0, max_length=25)
|
||||
stats_median = models.FloatField(default=0)
|
||||
|
||||
stats_candidates = models.FloatField(default=0)
|
||||
|
||||
stats_min = models.FloatField(default=0)
|
||||
stats_max = models.FloatField(default=0)
|
||||
|
||||
stats_max_possible = models.FloatField(default=0)
|
||||
|
||||
# stats_graph = models.TextField(default=0)
|
||||
|
||||
user_scores = models.JSONField(default=dict)
|
||||
|
||||
|
||||
exam_results_emailed = models.DateTimeField(default=None, null=True)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def save(self, *args, recreate_json=True, **kwargs):
|
||||
self.recreate_json = recreate_json
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def get_exam_stats(self, name=True):
|
||||
if self.stats_candidates < int(4):
|
||||
return f"- Candidates: {int(self.stats_candidates)} (too few to generate stats)"
|
||||
|
||||
text = f"""- Candidates: {int(self.stats_candidates)}
|
||||
- Mean: {self.stats_mean:.2f} Median: {self.stats_median} Mode: {self.stats_mode} [Min: {self.stats_min} / Max: {self.stats_max}]
|
||||
"""
|
||||
if name:
|
||||
text = f"""{self.name}
|
||||
{"-"*len(self.name)}
|
||||
{text}
|
||||
"""
|
||||
return text
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("{}:exam_overview".format(self.app_name), kwargs={"pk": self.pk})
|
||||
|
||||
def get_cid_edit_url(self):
|
||||
return reverse(
|
||||
"{}:exam_cids_edit".format(self.app_name), kwargs={"exam_id": self.pk}
|
||||
)
|
||||
|
||||
def get_user_edit_url(self):
|
||||
return reverse(
|
||||
"{}:exam_users_edit".format(self.app_name), kwargs={"exam_id": self.pk}
|
||||
)
|
||||
|
||||
def get_take_url(self):
|
||||
return f"{settings.REMOTE_URL}/rts"
|
||||
|
||||
def get_exam_name(self):
|
||||
return self.name
|
||||
|
||||
def get_json_url(self, cid=None, passcode=None):
|
||||
if cid is None:
|
||||
return reverse("{}:exam_json".format(self.app_name), args=(self.pk,))
|
||||
else:
|
||||
return reverse(
|
||||
"{}:exam_json_cid".format(self.app_name), args=(self.pk, cid, passcode)
|
||||
)
|
||||
|
||||
def get_question_index(self, question):
|
||||
return list(self.exam_questions.all()).index(question)
|
||||
|
||||
|
||||
def get_cid_user_score(self, cid_user):
|
||||
c = "c/" + str(cid_user)
|
||||
if c in self.user_scores:
|
||||
|
||||
Reference in New Issue
Block a user