from django.db import models from django.urls import reverse import tagulous import tagulous.models from sortedm2m.fields import SortedManyToManyField from django.conf import settings from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.core.mail import send_mail class Plane(models.Model): plane = models.CharField(max_length=200) def __str__(self): return self.plane class Meta: ordering = ("plane",) class Contrast(models.Model): contrast = models.CharField(max_length=200) def __str__(self): return self.contrast class Meta: ordering = ("contrast",) class Examination(models.Model): examination = models.CharField(max_length=200) def __str__(self): return self.examination class Meta: ordering = ("examination",) class Site(models.Model): site = models.CharField(max_length=200) initials = models.CharField(max_length=200) def __str__(self): return self.site class Condition(tagulous.models.TagModel): pass class Sign(tagulous.models.TagModel): 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") 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, ) 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, ) 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) # time_limit = models.IntegerField( # help_text="Exam time limit (in seconds). Default is 2100 secondse (35 minutes)", # default=2100, # ) class Meta: abstract = True 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_take_url(self): return f"{settings.REMOTE_URL}/rts" def get_exam_name(self): return self.name def get_json_url(self): return reverse("{}:exam_json".format(self.app_name), args=(self.pk,)) 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()]) return authors def get_author_objects(self): """Returns a comma seperated text list of authors""" authors = [i for i in self.author.all()] return authors def check_cid_user(self, cid, passcode): if self.valid_users.exists(): user = self.valid_users.filter(cid=cid).first() if not user or user.passcode != passcode: return False return True class NoteType(models.Model): note_type = models.CharField(max_length=200) def __str__(self): return self.note_type class QuestionNote(models.Model): content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() question = GenericForeignKey("content_type", "object_id") # author = models.ForeignKey(User, author = models.CharField(max_length=200, blank=True) user_author = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True ) note = models.TextField(blank=True) created_on = models.DateTimeField(auto_now_add=True) complete = models.BooleanField(default=False) note_type = models.ForeignKey( NoteType, on_delete=models.CASCADE, null=True, blank=True ) # def get_absolute_url(self): # self.pk = self.rapid_id # return reverse('rapids:question_detail', kwargs={'pk': self.pk}) def __str__(self): return "{}: {} [{}] {} / {}".format( self.content_type, self.get_author_str(), self.created_on, self.note_type, self.note, ) def get_absolute_url(self): # TODO: return to question if logged in return "/" def get_object_url(self): return self.question.get_absolute_url() def get_author_str(self): if self.user_author is not None: return self.user_author.username else: return self.author def get_short_str(self): return f"{self.note_type} - {self.note}" class CidUser(models.Model): cid = models.IntegerField(blank=True, null=True, unique=True) passcode = models.CharField(blank=True, max_length=50) active = models.BooleanField(default=True) internal_candidate = models.BooleanField(default=False) name = models.CharField(blank=True, max_length=255) email = models.EmailField(blank=True) supervisor_email = models.EmailField(blank=True) group = models.ForeignKey("CidUserGroup", on_delete=models.SET_NULL, null=True) def __str__(self) -> str: return str(self.cid) def check_passcode(self, passcode) -> bool: return self.passcode == passcode def email_details(self): msg = f""" See below for you details for: {self.group} --------- CID: {self.cid} Passcode: {self.passcode} --------- You will need these to login to the test system on the day. Please note this inbox is not monitored. Direct all enquiries to ... """ send_mail("Candidate Details", msg, "test@xkjq.uk", [self.email]) class CidUserExam(models.Model): content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() question = GenericForeignKey("content_type", "object_id") start_time = models.DateTimeField(blank=True, null=True) end_time = models.DateTimeField(blank=True, null=True) cid_user = models.ForeignKey(CidUser, on_delete=models.CASCADE) manual_submission = models.BooleanField(default=False) class CidUserGroup(models.Model): name = models.CharField(blank=True, max_length=50) archive = models.BooleanField(default=False) def __str__(self) -> str: return str(self.name)