further abstraction

This commit is contained in:
Ross
2023-06-12 11:35:15 +01:00
parent cbe7257fe8
commit e0f0c7619a
2 changed files with 125 additions and 115 deletions
+2 -3
View File
@@ -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
View File
@@ -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: