コード例 #1
0
class Test(models.Model):
    problem = models.ForeignKey(Problem)
    name = models.CharField(max_length=30, verbose_name=_("name"))
    input_file = FileField(upload_to=make_problem_filename,
                           verbose_name=_("input"),
                           null=True,
                           blank=True)
    output_file = FileField(upload_to=make_problem_filename,
                            verbose_name=_("output/hint"),
                            null=True,
                            blank=True)
    kind = EnumField(test_kinds, verbose_name=_("kind"))
    group = models.CharField(max_length=30, verbose_name=_("group"))
    time_limit = models.IntegerField(verbose_name=_("time limit (ms)"),
                                     null=True,
                                     blank=True)
    memory_limit = models.IntegerField(verbose_name=_("memory limit (KiB)"),
                                       null=True,
                                       blank=True)
    max_score = models.IntegerField(verbose_name=_("score"), default=10)
    order = models.IntegerField(default=0)

    class Meta:
        ordering = ['order']
        verbose_name = _("test")
        verbose_name_plural = _("tests")
コード例 #2
0
class ContestAttachment(models.Model):
    """Represents an additional file visible to the contestant, linked to
       the contest or to the round.

       This may be used for additional materials, like rules, documentation
       etc.
    """
    contest = models.ForeignKey(Contest,
                                related_name='c_attachments',
                                verbose_name=_("contest"))
    description = models.CharField(max_length=255,
                                   verbose_name=_("description"))
    content = FileField(upload_to=make_contest_filename,
                        verbose_name=_("content"))
    round = models.ForeignKey('Round',
                              related_name='r_attachments',
                              blank=True,
                              null=True,
                              verbose_name=_("round"))

    @property
    def filename(self):
        return os.path.split(self.content.name)[1]

    class Meta(object):
        verbose_name = _("attachment")
        verbose_name_plural = _("attachments")
コード例 #3
0
class ProblemAttachment(models.Model):
    """Represents an additional file visible to the contestant, linked to
       a problem.

       This may be used for things like input data for open data tasks, or for
       giving users additional libraries etc.
    """
    problem = models.ForeignKey(Problem, related_name='attachments')
    description = models.CharField(max_length=255,
                                   verbose_name=_("description"))
    content = FileField(upload_to=make_problem_filename,
                        verbose_name=_("content"))

    @property
    def filename(self):
        return os.path.split(self.content.name)[1]

    @property
    def download_name(self):
        return strip_num_or_hash(self.filename)

    class Meta(object):
        verbose_name = _("attachment")
        verbose_name_plural = _("attachments")

    def __unicode__(self):
        return '%s / %s' % (self.problem.name, self.filename)
コード例 #4
0
ファイル: models.py プロジェクト: JacquesWhite/oioioi
class MailSubmission(models.Model):
    problem_instance = models.ForeignKey(ProblemInstance,
                                         verbose_name=_("problem"),
                                         on_delete=models.CASCADE)
    user = models.ForeignKey(User,
                             blank=True,
                             null=True,
                             verbose_name=_("user"),
                             on_delete=models.CASCADE)
    date = models.DateTimeField(default=timezone.now,
                                blank=True,
                                verbose_name=_("date"),
                                db_index=True)
    source_file = FileField(upload_to=make_submission_filename)
    submission = models.ForeignKey(
        Submission,
        blank=True,
        null=True,
        verbose_name=_("related submission"),
        on_delete=models.CASCADE,
    )
    accepted_by = models.ForeignKey(
        User,
        blank=True,
        null=True,
        verbose_name=_("accepted by"),
        related_name='+',
        on_delete=models.SET_NULL,
    )
コード例 #5
0
ファイル: models.py プロジェクト: cytadela8/oioioi
class TestsPackage(models.Model):
    __test__ = False
    problem = models.ForeignKey(Problem)
    name = models.CharField(max_length=30, verbose_name=_("file name"),
            help_text=_("File name can only contain letters, digits,"
                " - and _. It should not contain file extension such as"
                " .zip, .tgz, etc."),
            validators=[RegexValidator(r'^[0-9a-zA-Z\-_]+$',
                _("Name can only contain letters, digits, - and _."))])
    description = models.TextField(null=False, blank=True)
    tests = models.ManyToManyField(Test)
    package = FileField(upload_to=make_problem_filename, null=True,
            blank=True, verbose_name=_("package"))
    publish_date = models.DateTimeField(null=True, blank=True,
            verbose_name=_("publish date"),
            help_text=_("If the date is left blank, the package will never "
                "be visible for participants of the contest."))

    _old_tests = None

    def is_visible(self, current_datetime):
        return self.publish_date is not None and \
                self.publish_date < current_datetime

    class Meta(object):
        verbose_name = _("tests package")
        verbose_name_plural = _("tests packages")
コード例 #6
0
class TestRunReport(models.Model):
    submission_report = models.ForeignKey(SubmissionReport)
    status = EnumField(submission_statuses)
    comment = models.CharField(max_length=255, blank=True)
    time_used = models.IntegerField(blank=True)
    test_time_limit = models.IntegerField(null=True, blank=True)
    output_file = FileField(upload_to=make_custom_output_filename)
コード例 #7
0
ファイル: models.py プロジェクト: Kerram/oioioi
class ContestAttachment(models.Model):
    """Represents an additional file visible to the contestant, linked to
       the contest or to the round.

       This may be used for additional materials, like rules, documentation
       etc.
    """
    contest = models.ForeignKey(Contest, related_name='c_attachments',
            verbose_name=_("contest"), on_delete=models.CASCADE)
    description = models.CharField(max_length=255,
            verbose_name=_("description"))
    content = FileField(upload_to=make_contest_filename,
            verbose_name=_("content"))
    round = models.ForeignKey('Round', related_name='r_attachments',
            blank=True, null=True, verbose_name=_("round"), on_delete=models.CASCADE)
    pub_date = models.DateTimeField(default=None, blank=True, null=True,
            verbose_name=_("publication date"))

    @property
    def filename(self):
        return os.path.split(self.content.name)[1]

    @property
    def download_name(self):
        return strip_num_or_hash(self.filename)

    def __unicode__(self):
        return self.filename

    class Meta(object):
        verbose_name = _("attachment")
        verbose_name_plural = _("attachments")
コード例 #8
0
class ProblemStatement(models.Model):
    """Represents a file containing problem statement.

       Problem may have multiple statements, for example in various languages
       or formats. Formats should be detected according to filename extension
       of :attr:`content`.
    """
    problem = models.ForeignKey(Problem, related_name='statements')
    language = models.CharField(max_length=6,
                                blank=True,
                                null=True,
                                verbose_name=_("language code"))
    content = FileField(upload_to=make_problem_filename,
                        verbose_name=_("content"))

    @property
    def filename(self):
        return os.path.split(self.content.name)[1]

    @property
    def download_name(self):
        return self.problem.short_name + self.extension

    @property
    def extension(self):
        return os.path.splitext(self.content.name)[1].lower()

    class Meta(object):
        verbose_name = _("problem statement")
        verbose_name_plural = _("problem statements")

    def __unicode__(self):
        return '%s / %s' % (self.problem.name, self.filename)
コード例 #9
0
class OutputChecker(models.Model):
    problem = models.OneToOneField(Problem)
    exe_file = FileField(upload_to=make_problem_filename,
            null=True, blank=True, verbose_name=_("checker executable file"))

    class Meta(object):
        verbose_name = _("output checker")
        verbose_name_plural = _("output checkers")
コード例 #10
0
class OriginalPackage(models.Model):
    problem = models.ForeignKey(Problem)
    package_file = FileField(upload_to=make_problem_filename,
                             verbose_name=_("package"))

    class Meta(object):
        verbose_name = _("original sinolpack package")
        verbose_name_plural = _("original sinolpack packages")
コード例 #11
0
class Test(models.Model):
    __test__ = False
    problem_instance = models.ForeignKey(ProblemInstance,
                                         on_delete=models.CASCADE)
    name = models.CharField(max_length=30, verbose_name=_("name"))
    input_file = FileField(upload_to=make_problem_filename,
                           verbose_name=_("input"),
                           null=True,
                           blank=True)
    output_file = FileField(
        upload_to=make_problem_filename,
        verbose_name=_("output/hint"),
        null=True,
        blank=True,
    )
    kind = EnumField(test_kinds, verbose_name=_("kind"))
    group = models.CharField(max_length=30, verbose_name=_("group"))
    time_limit = models.IntegerField(
        verbose_name=_("time limit (ms)"),
        null=True,
        blank=False,
        validators=[validate_time_limit],
    )
    memory_limit = models.IntegerField(
        verbose_name=_("memory limit (KiB)"),
        null=True,
        blank=True,
        validators=[validate_memory_limit],
    )
    max_score = models.IntegerField(verbose_name=_("score"), default=10)
    order = models.IntegerField(default=0)
    is_active = models.BooleanField(default=True)

    @property
    def problem(self):
        return self.problem_instance.problem

    def __str__(self):
        return six.text_type(self.name)

    class Meta(object):
        ordering = ['order']
        verbose_name = _("test")
        verbose_name_plural = _("tests")
        unique_together = ('problem_instance', 'name')
コード例 #12
0
class ProgramSubmission(Submission):
    source_file = FileField(upload_to=make_submission_filename)
    source_length = models.IntegerField(verbose_name=_("Source code length"),
                                        blank=True, null=True)

    def save(self, *args, **kwargs):
        if self.source_file:
            self.source_length = self.source_file.size
        super(ProgramSubmission, self).save(*args, **kwargs)
コード例 #13
0
class ExtraFile(models.Model):
    """Model to store extra files (for example ``extra.zip``) present in some
       Sinol packages."""
    problem = models.ForeignKey(Problem)
    name = models.CharField(max_length=255, verbose_name=_("name"))
    file = FileField(upload_to=make_problem_filename)

    class Meta(object):
        verbose_name = _("sinolpack's extra file")
        verbose_name_plural = _("sinolpack's extra files")
コード例 #14
0
class ModelSolution(models.Model):
    objects = ModelSolutionsManager()

    problem = models.ForeignKey(Problem)
    name = models.CharField(max_length=30, verbose_name=_("name"))
    source_file = FileField(upload_to=make_problem_filename,
                            verbose_name=_("source"))
    kind = EnumField(model_solution_kinds, verbose_name=_("kind"))

    @property
    def short_name(self):
        return self.name.rsplit('.', 1)[0]
コード例 #15
0
ファイル: models.py プロジェクト: pragacz/oioioi
class ProgramSubmission(Submission):
    source_file = FileField(upload_to=make_submission_filename)
    source_length = models.IntegerField(verbose_name=_("Source code length"),
                                        blank=True,
                                        null=True)

    def save(self, *args, **kwargs):
        if self.source_file:
            self.source_length = self.source_file.size
        super(ProgramSubmission, self).save(*args, **kwargs)

    @property
    def extension(self):
        return os.path.splitext(self.source_file.name)[1][1:]

    def get_language_display(self):
        return get_language_by_extension(self.problem_instance, self.extension)
コード例 #16
0
class ContestIcon(models.Model):
    contest = models.ForeignKey(Contest, verbose_name=_("contest"))
    image = FileField(upload_to=make_icon_filename,
                      verbose_name=_('icon image'))
    updated_at = models.DateTimeField(default=timezone.now)

    def save(self, *args, **kwargs):
        self.updated_at = timezone.now()
        return super(ContestIcon, self).save(*args, **kwargs)

    @property
    def filename(self):
        return os.path.split(self.image.name)[1]

    class Meta(object):
        verbose_name = _("contest icon")
        verbose_name_plural = _("contest icons")
コード例 #17
0
ファイル: models.py プロジェクト: marmistrz/oioioi
class TestReport(models.Model):
    submission_report = models.ForeignKey(SubmissionReport)
    status = EnumField(submission_statuses)
    comment = models.CharField(max_length=255, blank=True)
    score = ScoreField(null=True, blank=True)
    time_used = models.IntegerField(blank=True)
    output_file = FileField(upload_to=make_output_filename,
                            null=True,
                            blank=True)

    test = models.ForeignKey(Test,
                             blank=True,
                             null=True,
                             on_delete=models.SET_NULL)
    test_name = models.CharField(max_length=30)
    test_group = models.CharField(max_length=30)
    test_time_limit = models.IntegerField(null=True, blank=True)
    test_max_score = models.IntegerField(null=True, blank=True)
コード例 #18
0
class ContestLogo(models.Model):
    contest = models.OneToOneField(Contest,
                                   verbose_name=_("contest"),
                                   primary_key=True)
    image = FileField(upload_to=make_logo_filename,
                      verbose_name=_("logo image"))
    updated_at = models.DateTimeField(default=timezone.now)

    def save(self, *args, **kwargs):
        self.updated_at = timezone.now()
        return super(ContestLogo, self).save(*args, **kwargs)

    @property
    def filename(self):
        return os.path.split(self.image.name)[1]

    class Meta(object):
        verbose_name = _("contest logo")
        verbose_name_plural = _("contest logo")
コード例 #19
0
class OutputChecker(models.Model):
    problem = models.OneToOneField(Problem)
    exe_file = FileField(upload_to=make_problem_filename,
            null=True, blank=True)
コード例 #20
0
class TestRunProgramSubmission(ProgramSubmission):
    input_file = FileField(upload_to=make_custom_input_filename)
コード例 #21
0
class ZeusTestRunProgramSubmission(TestRunProgramSubmission):
    library_file = FileField(upload_to=make_custom_library_filename, null=True)
コード例 #22
0
class ExtraFile(models.Model):
    """Model to store extra files (for example ``extra.zip``) present in some
       Sinol packages."""
    problem = models.ForeignKey(Problem)
    name = models.CharField(max_length=255)
    file = FileField(upload_to=make_problem_filename)
コード例 #23
0
class ProgramSubmission(Submission):
    source_file = FileField(upload_to=make_submission_filename)
コード例 #24
0
class OriginalPackage(models.Model):
    problem = models.ForeignKey(Problem)
    package_file = FileField(upload_to=make_problem_filename)
コード例 #25
0
ファイル: models.py プロジェクト: Kerram/oioioi
class PrizeGiving(models.Model):
    """Represents an event of distributing prizes to users.

       Such an event needs some proper preparation.
       First of all, we decide on a date when it's going to happen.
       Secondly, we decide on a list of Prizes to be distributed.
       Finally, we specify a distributor, which will effectively assign Prizes
       to users creating PrizeForUser objects.

       To make it all work together, we set up a celery worker to which we send
       scheduled distribution tasks. Each time a PrizeGiving object is
       changed in a way that makes recently sent task irrelevant the task
       is invalidated and a new task is sent if needed.
    """
    # Usage:
    # pg = PrizeGiving.objects.create(contest=c, date=..., name=..., key=...)
    # Prize.objects.create(contest=c, prize_giving=pg, ...)
    # pg.schedule() -- you don't have to call it immediately
    #
    # You can change parameters if ``pg`` hasn't taken place yet:
    # pg.update(contest=..., date=..., name=..., key=...)
    # pg.schedule()
    #
    # Later, when ``pg`` has already succeeded or failed,
    # in order to undo everything and start the logic again,
    # you will need to specify 'force_reset=True' with ``update``:
    # pg.update(force_reset=True, ...)
    # pg.schedule()
    #
    # At any time you can delete ``pg`` as if it has never existed.
    # pg.delete()

    contest = models.ForeignKey(Contest, on_delete=models.CASCADE)
    date = models.DateTimeField(_("Distribution date"),
                                blank=True,
                                null=True,
                                help_text=_("Leave blank for 'later'."))
    name = models.CharField(_("name"),
                            max_length=100,
                            help_text=_("Prize-givings with the same name "
                                        "are listed together."))
    # key in dictionary returned by ContestController.get_prizes_distributors()
    key = models.CharField(_("awarding rules"),
                           max_length=100,
                           choices=[('', '')])

    # read-only fields
    state = EnumField(prizegiving_states,
                      default='NOT_SCHEDULED',
                      editable=False)
    report = FileField(upload_to=_make_report_filename,
                       null=True,
                       editable=False)

    # private fields
    version = models.DateTimeField(default=timezone.now, editable=False)

    class Meta(object):
        verbose_name = _("prize-giving")
        verbose_name_plural = _("prize-givings")
        ordering = ['-date', 'id']

    def _distribute(self, on_success=lambda: None, on_failure=lambda: None):
        try:
            _name, distributor = \
                    self.contest.controller.get_prizes_distributors()[self.key]
            distributor(self)
            self.state = 'SUCCESS'
            report = generate_success_report(self)
            on_success()
        except AssignmentNotFound as e:
            e.send_email()
            self.date = None
            self.state = 'FAILURE'
            report = e.report
            on_failure()
            # The related PrizeForUsers are deleted in call to `save`.

        self._set_report(report)
        self._change_version()
        self.save()

    def _set_report(self, report):
        if report is not None:
            filename = 'id%s__v%s__%s.csv' % \
                    (self.id, self.version, self.state)
            report = ContentFile(report, filename)

        self.report = report

    def _send_task_to_worker(self):
        prizesmgr_job.apply_async(args=[self.pk, self.version], eta=self.date)

    def _delegate_distribution(self):
        self.state = 'SCHEDULED'
        self.save()
        self._send_task_to_worker()

    def _distribute_in_place(self):
        self.date = timezone.now()
        self._distribute()

    def schedule(self):
        """Schedule to happen.

           You need to call it both after creating a new PrizeGiving
           or updating an old one.
           Note, that here we refer to an event rather than a particular
           PrizeGiving instance representing it. For example, you can save
           information about PrizeGiving to the database using a PrizeGiving
           instance, retrieve a new instance representing it two days later,
           and call `schedule` on it.

           If PrizeGiving is past its date, the distribution will be
           triggered from within this funtion.

           It calls `save` behind the scenes.
        """
        if self.state == 'NOT_SCHEDULED' and self.date:
            self._change_version()
            # Take into account that user chooses "now" with 1 minute accuracy
            if self.date >= timezone.now() + timedelta(minutes=1):
                self._delegate_distribution()
            else:
                self._distribute_in_place()

    def _celery_task_invalid(self):
        """Check if there is a valid celery task that now must be invalidated.
        """
        try:
            old_self = PrizeGiving.objects.select_for_update().get(pk=self.pk)
        except PrizeGiving.DoesNotExist:
            old_self = PrizeGiving()

        if old_self.state != 'SCHEDULED':
            return False

        def essential_params(pg):
            return model_to_dict(pg, fields=['state', 'date'])

        return essential_params(old_self) != essential_params(self)

    def _change_version(self):
        self.version = timezone.now()

    def update(self, commit=True, force_reset=False, **kwargs):
        """Always call this method after changing public attributes.
           For convenience, you can set attributes and update in one step
           using keyword arguments.
        """
        for key, value in kwargs.items():
            setattr(self, key, value)

        if force_reset:
            self._set_report(None)

        if force_reset or self._celery_task_invalid():
            self.state = 'NOT_SCHEDULED'
            self._change_version()

        # In case the previous state was 'SUCCESS' and it changed, the
        # related PrizeForUsers are deleted in call to `save`.

        if commit:
            self.save()

    def save(self, *args, **kwargs):
        # PrizeGiving can have related PrizeForUsers in 'SUCCESS' state only.
        if self.state != 'SUCCESS':
            PrizeForUser.objects.filter(prize__prize_giving=self).delete()

        return super(PrizeGiving, self).save(*args, **kwargs)

    def clean_fields(self, *args, **kwargs):
        if 'key' not in kwargs['exclude']:
            kwargs['exclude'].append('key')
        super(PrizeGiving, self).clean_fields(*args, **kwargs)

    def clean(self):
        if self.key not in self.contest.controller.get_prizes_distributors():
            raise ValidationError(
                _("Invalid value for position in distribution order."))

    def __unicode__(self):
        suffix = timezone.localtime(self.date).strftime(' (%m-%d %H:%M)') \
                if self.date else ''
        return self.name + suffix
コード例 #26
0
class ProblemPackage(models.Model):
    """Represents a file with data necessary for creating a
       :class:`~oioioi.problems.models.Problem` instance.
    """
    package_file = FileField(upload_to=_make_package_filename,
                             verbose_name=_("package"))
    contest = models.ForeignKey('contests.Contest',
                                null=True,
                                blank=True,
                                verbose_name=_("contest"))
    problem = models.ForeignKey(Problem,
                                verbose_name=_("problem"),
                                null=True,
                                blank=True)
    created_by = models.ForeignKey(User,
                                   verbose_name=_("created by"),
                                   null=True,
                                   blank=True)
    problem_name = models.CharField(max_length=30,
                                    validators=[validate_slug],
                                    verbose_name=_("problem name"),
                                    null=True,
                                    blank=True)
    celery_task_id = models.CharField(max_length=50,
                                      unique=True,
                                      null=True,
                                      blank=True)
    info = models.CharField(max_length=1000,
                            null=True,
                            blank=True,
                            verbose_name=_("Package information"))
    traceback = FileField(upload_to=_make_package_filename,
                          verbose_name=_("traceback"),
                          null=True,
                          blank=True)
    status = EnumField(package_statuses, default='?', verbose_name=_("status"))
    creation_date = models.DateTimeField(default=timezone.now)

    @property
    def download_name(self):
        ext = split_extension(self.package_file.name)[1]
        if self.problem:
            return self.problem.short_name + ext
        else:
            filename = os.path.split(self.package_file.name)[1]
            return strip_num_or_hash(filename)

    class Meta(object):
        verbose_name = _("problem package")
        verbose_name_plural = _("problem packages")
        ordering = ['-creation_date']

    class StatusSaver(object):
        def __init__(self, package):
            self.package_id = package.id

        def __enter__(self):
            pass

        def __exit__(self, type, value, traceback):
            package = ProblemPackage.objects.get(id=self.package_id)
            if type:
                package.status = 'ERR'
                # Truncate error so it doesn't take up whole page in list
                # view. Full info is available anyway in package.traceback.
                package.info = Truncator(value).chars(400)
                package.traceback = ContentFile(
                    ''.join(
                        format_exception(type, value, traceback,
                                         TRACEBACK_STACK_LIMIT)),
                    'traceback.txt')
                logger.exception("Error processing package %s",
                                 package.package_file.name,
                                 extra={'omit_sentry': True})
            else:
                package.status = 'OK'

            # Truncate message to fit in db.
            package.info = Truncator(package.info).chars(1000)

            package.celery_task_id = None
            package.save()
            return True

    def save_operation_status(self):
        """Returns a context manager to be used during the unpacking process.

           The code inside the ``with`` statment is executed in a transaction.

           If the code inside the ``with`` statement executes successfully,
           the package ``status`` field is set to ``OK``.

           If an exception is thrown, it gets logged together with the
           traceback. Additionally, its value is saved in the package
           ``info`` field.

           Lastly, if the package gets deleted from the database before
           the ``with`` statement ends, a
           :class:`oioioi.problems.models.ProblemPackage.DoesNotExist`
           exception is thrown.
        """
        @contextmanager
        def manager():
            with self.StatusSaver(self), transaction.atomic():
                yield None

        return manager()
コード例 #27
0
ファイル: models.py プロジェクト: matrach/oioioi
 class TestFileModel(models.Model):
     file_field = FileField(upload_to='tests')