class EjudgeEntranceExamTask(EntranceExamTask): type_title = 'Практические задачи' ejudge_contest_id = models.PositiveIntegerField( help_text='ID контеста в еджадже') ejudge_problem_id = models.PositiveIntegerField( help_text='ID задачи в еджадже') def is_accepted_for_user(self, user): return self.is_solved_by_user(user) def is_solved_by_user(self, user): user_solutions = self.solution_class.objects.filter( user=user, task=self).select_related( 'ejudge_queue_element__submission__result') task_has_ok = any( filter(lambda s: s.is_checked and s.result.is_success, user_solutions)) return task_has_ok @property def solutions_template_file(self): raise NotImplementedError( 'Child should define property solutions_template_file') class Meta: abstract = True
class Image(AbstractDocumentBlock): filename = relativefilepathfield.fields.RelativeFilePathField( path=django.db.migrations.writer.SettingsReference( settings.SISTEMA_GENERATOR_ASSETS_DIR, 'SISTEMA_GENERATOR_ASSETS_DIR', ), recursive=True) width = models.PositiveIntegerField( null=True, blank=True, default=None, help_text='В пунктах. Оставьте пустым, чтобы взять размеры самой ' 'картинки', ) height = models.PositiveIntegerField( null=True, blank=True, default=None, help_text='В пунктах. Оставьте пустым, чтобы взять размеры самой ' 'картинки', ) def get_reportlab_block(self, visitor=None): self._process_by_visitor(visitor) return reportlab.platypus.Image(self.get_filename_abspath(), width=self.width, height=self.height)
class Spacer(AbstractDocumentBlock): width = models.PositiveIntegerField() height = models.PositiveIntegerField() is_glue = models.BooleanField(default=False) def __str__(self): return 'Spacer %dx%d' % (self.width, self.height) def get_reportlab_block(self, visitor=None): self._process_by_visitor(visitor) return reportlab.platypus.Spacer(self.width, self.height, self.is_glue)
class TableCell(models.Model, ProcessedByVisitor): row = models.ForeignKey( TableRow, on_delete=models.CASCADE, related_name='cells', ) block = models.ForeignKey( AbstractDocumentBlock, on_delete=models.CASCADE, related_name='+', ) order = models.PositiveIntegerField( help_text='Ячейки упорядочиваются по возрастанию порядка') class Meta: ordering = ('row', 'order') unique_together = ('row', 'order') def __str__(self): return '%s[%d]: %s' % (self.row, self.order, self.block) def get_reportlab_block(self, visitor): self._process_by_visitor(visitor) return self.block.get_reportlab_block(visitor)
class UserQuestionnaireStatus(models.Model): class Status(djchoices.DjangoChoices): NOT_FILLED = djchoices.ChoiceItem(1) FILLED = djchoices.ChoiceItem(2) user = models.ForeignKey( users.models.User, on_delete=models.CASCADE, related_name='+', ) questionnaire = models.ForeignKey( Questionnaire, on_delete=models.CASCADE, related_name='statuses', ) status = models.PositiveIntegerField( choices=Status.choices, validators=[Status.validator], ) class Meta: verbose_name_plural = 'user questionnaire statuses' unique_together = ('user', 'questionnaire') def __str__(self): return 'Status {} of {} for {}'.format(self.status, self.questionnaire, self.user)
class FontTableStyleCommand(CellFormattingTableStyleCommand): command_name = 'FONT' command_params = ['font.name', 'size'] font = models.ForeignKey(Font, on_delete=models.CASCADE) size = models.PositiveIntegerField(null=True, default=None, blank=True)
class ParagraphStyle(models.Model): name = models.CharField(max_length=100) leading = models.FloatField() alignment = models.PositiveIntegerField( choices=Alignment.choices, validators=[Alignment.validator], ) font = models.ForeignKey( Font, on_delete=models.CASCADE, related_name='+', ) font_size = models.PositiveIntegerField() bullet_font = models.ForeignKey( Font, on_delete=models.CASCADE, related_name='+', ) space_before = models.PositiveIntegerField() space_after = models.PositiveIntegerField() left_indent = models.PositiveIntegerField() def __str__(self): return self.name def get_reportlab_style(self): return reportlab.lib.styles.ParagraphStyle( name=self.name, leading=self.leading, fontName=self.font.name, fontSize=self.font_size, bulletFontName=self.bullet_font.name, alignment=self.alignment, spaceBefore=self.space_before, spaceAfter=self.space_after, leftIndent=self.left_indent, )
class ScoreByPlaceAdditionalScorer(AbstractAdditionalScorer): """ Additional scores to first solved task teams """ place = models.PositiveIntegerField( help_text='I.e. 1 for team who first solved the task') points = models.IntegerField() def __str__(self): return '%d additional points for %d team' % (self.points, self.place)
class PaddingTableStyleCommand(CellFormattingTableStyleCommand): command_params = ['padding'] direction = models.CharField(max_length=6, choices=[('LEFT', 'Left'), ('RIGHT', 'Right'), ('BOTTOM', 'Bottom'), ('TOP', 'Top')]) padding = models.PositiveIntegerField(help_text='В пунктах') @property def command_name(self): return '%sPADDING' % (self.direction, )
class DateQuestionnaireQuestion(AbstractQuestionnaireQuestion): block_name = 'date_question' with_year = models.BooleanField(default=True) min_year = models.PositiveIntegerField(null=True) max_year = models.PositiveIntegerField(null=True) def get_form_field(self, attrs=None): return django.forms.DateField( required=self.is_required, disabled=self.is_disabled, label=self.text, help_text=self.help_text, widget=django.forms.DateInput( attrs={ 'class': 'gui-input datetimepicker', 'data-format': 'DD.MM.YYYY', 'data-view-mode': 'years', 'data-pick-time': 'false', 'placeholder': 'дд.мм.гггг', }), )
class GroupAccess(polymorphic.models.PolymorphicModel): class Type(djchoices.DjangoChoices): NONE = djchoices.ChoiceItem( value=0, label='Нет доступа, группа не видна', ) LIST_MEMBERS = djchoices.ChoiceItem( value=10, label='Может просматривать участников', ) EDIT_MEMBERS = djchoices.ChoiceItem( value=20, label='Может добавлять и удалять участников', ) ADMIN = djchoices.ChoiceItem( value=30, label='Полный доступ', ) to_group = models.ForeignKey( AbstractGroup, related_name='accesses', on_delete=models.CASCADE, ) access_type = models.PositiveIntegerField( choices=Type.choices, validators=[Type.validator], db_index=True, ) created_by = models.ForeignKey( users.models.User, related_name='+', on_delete=models.CASCADE, null=True, blank=True, help_text='Кем выдан доступ. Если None, то системой') created_at = models.DateTimeField( auto_now_add=True, db_index=True, ) class Meta: verbose_name = 'group access' verbose_name_plural = 'group accesses'
class ChoiceQuestionnaireQuestionVariant(models.Model): text = models.TextField() question = models.ForeignKey('ChoiceQuestionnaireQuestion', on_delete=models.CASCADE, related_name='variants') order = models.PositiveIntegerField(default=0) # If variant is disabled it shows as gray and can't be selected is_disabled = models.BooleanField(default=False) # If this one is selected all options are disabled disable_question_if_chosen = models.BooleanField(default=False) def __str__(self): return '{}: {} {}'.format(self.question, self.id, self.text)
class AbstractDocumentBlock(polymorphic.models.PolymorphicModel, ProcessedByVisitor): document = models.ForeignKey( Document, on_delete=models.CASCADE, null=True, blank=True, default=None, related_name='blocks', ) order = models.PositiveIntegerField( help_text='Блоки выстраиваются по возрастанию порядка', ) class Meta: verbose_name = 'document block' unique_together = ('document', 'order') ordering = ('document', 'order') def get_reportlab_block(self, visitor=None): raise NotImplementedError( 'Child should implement its own get_reportlab_block()')
class ProgramEntranceExamTask(EjudgeEntranceExamTask): template_file = 'program.html' solutions_template_file = '_program_solutions.html' input_file_name = models.CharField(max_length=100, blank=True) output_file_name = models.CharField(max_length=100, blank=True) time_limit = models.PositiveIntegerField(help_text='В миллисекундах') # Use FileSizeField to be able to define memory limit with units (i.e. 256M) memory_limit = sizefield.models.FileSizeField() input_format = models.TextField(blank=True) output_format = models.TextField(blank=True) def get_form_for_user(self, user, *args, **kwargs): return forms.ProgramEntranceTaskForm(self, *args, **kwargs) @property def solution_class(self): return ProgramEntranceExamTaskSolution
class TableRow(models.Model, ProcessedByVisitor): table = models.ForeignKey( Table, on_delete=models.CASCADE, related_name='rows', ) order = models.PositiveIntegerField( help_text='Строки упорядочиваются по возрастанию порядка') class Meta: ordering = ('table', 'order') unique_together = ('table', 'order') def __str__(self): return '%s[%d]' % (self.table, self.order) def get_reportlab_row(self, visitor): self._process_by_visitor(visitor) return [ c.get_reportlab_block(visitor) for c in self.cells.order_by('order') ]
class EntranceExamTask(polymorphic.models.PolymorphicModel): title = models.CharField(max_length=100, help_text='Название') text = models.TextField(help_text='Формулировка задания') exam = models.ForeignKey( 'EntranceExam', on_delete=models.CASCADE, related_name='%(class)s', ) category = models.ForeignKey( 'EntranceExamTaskCategory', on_delete=models.CASCADE, verbose_name='категория', related_name='tasks', ) help_text = models.CharField( max_length=100, help_text='Дополнительная информация, например, сведения о формате ' 'ответа', blank=True) order = models.IntegerField( help_text='Задачи выстраиваются по возрастанию порядка', default=0) max_score = models.PositiveIntegerField() custom_description = models.TextField( help_text='Текст с описанием типа задачи. Оставьте пустым, тогда будет ' 'использован текст по умолчанию для данного вида задач. ' 'В этом тексте можно указать, например, ' 'для кого эта задача предназначена.\n' 'Поддерживается Markdown', blank=True, ) def __str__(self): return "{}: {}".format(self.exam.school.name, self.title) def save(self, *args, **kwargs): if self.category.exam_id != self.exam_id: raise IntegrityError( "{}.{}: task's category should belong to the same exam as the " "task itself".format(self.__module__, self.__class__.__name__)) super().save(*args, **kwargs) def is_accepted_for_user(self, user): # Always not accepted by default. Override when subclassing. return False def is_solved_by_user(self, user): # Always not solved by default. Override when subclassing. return False @property def template_file(self): """ Return template file name in folder templates/entrance/exam/ """ raise NotImplementedError('Child should define property template_file') @property def type_title(self): """ Return title of blocks with these tasks """ raise NotImplementedError('Child should define property type_title') def get_form_for_user(self, user, *args, **kwargs): """ Return form for this task for the specified user """ raise NotImplementedError('Child should define get_form_for_user()') @property def solution_class(self): raise NotImplementedError( 'Child should define property solution_class')
class LeadingTableStyleCommand(CellFormattingTableStyleCommand): command_name = 'LEADING' command_params = ['leading'] leading = models.PositiveIntegerField(help_text='В пунктах')