Reformat using black

This commit is contained in:
cuom1999 2022-05-14 12:57:27 -05:00
parent efee4ad081
commit a87fb49918
221 changed files with 19127 additions and 7310 deletions

View file

@ -19,143 +19,286 @@ from judge.models.runtime import Language
from judge.user_translations import gettext as user_gettext
from judge.utils.raw_sql import RawSQLColumn, unique_together_left_join
__all__ = ['ProblemGroup', 'ProblemType', 'Problem', 'ProblemTranslation', 'ProblemClarification',
'License', 'Solution', 'TranslatedProblemQuerySet', 'TranslatedProblemForeignKeyQuerySet']
__all__ = [
"ProblemGroup",
"ProblemType",
"Problem",
"ProblemTranslation",
"ProblemClarification",
"License",
"Solution",
"TranslatedProblemQuerySet",
"TranslatedProblemForeignKeyQuerySet",
]
class ProblemType(models.Model):
name = models.CharField(max_length=20, verbose_name=_('problem category ID'), unique=True)
full_name = models.CharField(max_length=100, verbose_name=_('problem category name'))
name = models.CharField(
max_length=20, verbose_name=_("problem category ID"), unique=True
)
full_name = models.CharField(
max_length=100, verbose_name=_("problem category name")
)
def __str__(self):
return self.full_name
class Meta:
ordering = ['full_name']
verbose_name = _('problem type')
verbose_name_plural = _('problem types')
ordering = ["full_name"]
verbose_name = _("problem type")
verbose_name_plural = _("problem types")
class ProblemGroup(models.Model):
name = models.CharField(max_length=20, verbose_name=_('problem group ID'), unique=True)
full_name = models.CharField(max_length=100, verbose_name=_('problem group name'))
name = models.CharField(
max_length=20, verbose_name=_("problem group ID"), unique=True
)
full_name = models.CharField(max_length=100, verbose_name=_("problem group name"))
def __str__(self):
return self.full_name
class Meta:
ordering = ['full_name']
verbose_name = _('problem group')
verbose_name_plural = _('problem groups')
ordering = ["full_name"]
verbose_name = _("problem group")
verbose_name_plural = _("problem groups")
class License(models.Model):
key = models.CharField(max_length=20, unique=True, verbose_name=_('key'),
validators=[RegexValidator(r'^[-\w.]+$', r'License key must be ^[-\w.]+$')])
link = models.CharField(max_length=256, verbose_name=_('link'))
name = models.CharField(max_length=256, verbose_name=_('full name'))
display = models.CharField(max_length=256, blank=True, verbose_name=_('short name'),
help_text=_('Displayed on pages under this license'))
icon = models.CharField(max_length=256, blank=True, verbose_name=_('icon'), help_text=_('URL to the icon'))
text = models.TextField(verbose_name=_('license text'))
key = models.CharField(
max_length=20,
unique=True,
verbose_name=_("key"),
validators=[RegexValidator(r"^[-\w.]+$", r"License key must be ^[-\w.]+$")],
)
link = models.CharField(max_length=256, verbose_name=_("link"))
name = models.CharField(max_length=256, verbose_name=_("full name"))
display = models.CharField(
max_length=256,
blank=True,
verbose_name=_("short name"),
help_text=_("Displayed on pages under this license"),
)
icon = models.CharField(
max_length=256,
blank=True,
verbose_name=_("icon"),
help_text=_("URL to the icon"),
)
text = models.TextField(verbose_name=_("license text"))
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('license', args=(self.key,))
return reverse("license", args=(self.key,))
class Meta:
verbose_name = _('license')
verbose_name_plural = _('licenses')
verbose_name = _("license")
verbose_name_plural = _("licenses")
class TranslatedProblemQuerySet(SearchQuerySet):
def __init__(self, **kwargs):
super(TranslatedProblemQuerySet, self).__init__(('code', 'name', 'description'), **kwargs)
super(TranslatedProblemQuerySet, self).__init__(
("code", "name", "description"), **kwargs
)
def add_i18n_name(self, language):
queryset = self._clone()
alias = unique_together_left_join(queryset, ProblemTranslation, 'problem', 'language', language)
return queryset.annotate(i18n_name=Coalesce(RawSQL('%s.name' % alias, ()), F('name'),
output_field=models.CharField()))
alias = unique_together_left_join(
queryset, ProblemTranslation, "problem", "language", language
)
return queryset.annotate(
i18n_name=Coalesce(
RawSQL("%s.name" % alias, ()),
F("name"),
output_field=models.CharField(),
)
)
class TranslatedProblemForeignKeyQuerySet(QuerySet):
def add_problem_i18n_name(self, key, language, name_field=None):
queryset = self._clone() if name_field is None else self.annotate(_name=F(name_field))
alias = unique_together_left_join(queryset, ProblemTranslation, 'problem', 'language', language,
parent_model=Problem)
queryset = (
self._clone() if name_field is None else self.annotate(_name=F(name_field))
)
alias = unique_together_left_join(
queryset,
ProblemTranslation,
"problem",
"language",
language,
parent_model=Problem,
)
# You must specify name_field if Problem is not yet joined into the QuerySet.
kwargs = {key: Coalesce(RawSQL('%s.name' % alias, ()),
F(name_field) if name_field else RawSQLColumn(Problem, 'name'),
output_field=models.CharField())}
kwargs = {
key: Coalesce(
RawSQL("%s.name" % alias, ()),
F(name_field) if name_field else RawSQLColumn(Problem, "name"),
output_field=models.CharField(),
)
}
return queryset.annotate(**kwargs)
class Problem(models.Model):
code = models.CharField(max_length=20, verbose_name=_('problem code'), unique=True,
validators=[RegexValidator('^[a-z0-9]+$', _('Problem code must be ^[a-z0-9]+$'))],
help_text=_('A short, unique code for the problem, '
'used in the url after /problem/'))
name = models.CharField(max_length=100, verbose_name=_('problem name'), db_index=True,
help_text=_('The full name of the problem, '
'as shown in the problem list.'))
description = models.TextField(verbose_name=_('problem body'))
authors = models.ManyToManyField(Profile, verbose_name=_('creators'), blank=True, related_name='authored_problems',
help_text=_('These users will be able to edit the problem, '
'and be listed as authors.'))
curators = models.ManyToManyField(Profile, verbose_name=_('curators'), blank=True, related_name='curated_problems',
help_text=_('These users will be able to edit the problem, '
'but not be listed as authors.'))
testers = models.ManyToManyField(Profile, verbose_name=_('testers'), blank=True, related_name='tested_problems',
help_text=_(
'These users will be able to view the private problem, but not edit it.'))
types = models.ManyToManyField(ProblemType, verbose_name=_('problem types'),
help_text=_('The type of problem, '
"as shown on the problem's page."))
group = models.ForeignKey(ProblemGroup, verbose_name=_('problem group'), on_delete=CASCADE,
help_text=_('The group of problem, shown under Category in the problem list.'))
time_limit = models.FloatField(verbose_name=_('time limit'),
help_text=_('The time limit for this problem, in seconds. '
'Fractional seconds (e.g. 1.5) are supported.'),
validators=[MinValueValidator(settings.DMOJ_PROBLEM_MIN_TIME_LIMIT),
MaxValueValidator(settings.DMOJ_PROBLEM_MAX_TIME_LIMIT)])
memory_limit = models.PositiveIntegerField(verbose_name=_('memory limit'),
help_text=_('The memory limit for this problem, in kilobytes '
'(e.g. 64mb = 65536 kilobytes).'),
validators=[MinValueValidator(settings.DMOJ_PROBLEM_MIN_MEMORY_LIMIT),
MaxValueValidator(settings.DMOJ_PROBLEM_MAX_MEMORY_LIMIT)])
code = models.CharField(
max_length=20,
verbose_name=_("problem code"),
unique=True,
validators=[
RegexValidator("^[a-z0-9]+$", _("Problem code must be ^[a-z0-9]+$"))
],
help_text=_(
"A short, unique code for the problem, " "used in the url after /problem/"
),
)
name = models.CharField(
max_length=100,
verbose_name=_("problem name"),
db_index=True,
help_text=_("The full name of the problem, " "as shown in the problem list."),
)
description = models.TextField(verbose_name=_("problem body"))
authors = models.ManyToManyField(
Profile,
verbose_name=_("creators"),
blank=True,
related_name="authored_problems",
help_text=_(
"These users will be able to edit the problem, " "and be listed as authors."
),
)
curators = models.ManyToManyField(
Profile,
verbose_name=_("curators"),
blank=True,
related_name="curated_problems",
help_text=_(
"These users will be able to edit the problem, "
"but not be listed as authors."
),
)
testers = models.ManyToManyField(
Profile,
verbose_name=_("testers"),
blank=True,
related_name="tested_problems",
help_text=_(
"These users will be able to view the private problem, but not edit it."
),
)
types = models.ManyToManyField(
ProblemType,
verbose_name=_("problem types"),
help_text=_("The type of problem, " "as shown on the problem's page."),
)
group = models.ForeignKey(
ProblemGroup,
verbose_name=_("problem group"),
on_delete=CASCADE,
help_text=_("The group of problem, shown under Category in the problem list."),
)
time_limit = models.FloatField(
verbose_name=_("time limit"),
help_text=_(
"The time limit for this problem, in seconds. "
"Fractional seconds (e.g. 1.5) are supported."
),
validators=[
MinValueValidator(settings.DMOJ_PROBLEM_MIN_TIME_LIMIT),
MaxValueValidator(settings.DMOJ_PROBLEM_MAX_TIME_LIMIT),
],
)
memory_limit = models.PositiveIntegerField(
verbose_name=_("memory limit"),
help_text=_(
"The memory limit for this problem, in kilobytes "
"(e.g. 64mb = 65536 kilobytes)."
),
validators=[
MinValueValidator(settings.DMOJ_PROBLEM_MIN_MEMORY_LIMIT),
MaxValueValidator(settings.DMOJ_PROBLEM_MAX_MEMORY_LIMIT),
],
)
short_circuit = models.BooleanField(default=False)
points = models.FloatField(verbose_name=_('points'),
help_text=_('Points awarded for problem completion. '
"Points are displayed with a 'p' suffix if partial."),
validators=[MinValueValidator(settings.DMOJ_PROBLEM_MIN_PROBLEM_POINTS)])
partial = models.BooleanField(verbose_name=_('allows partial points'), default=False)
allowed_languages = models.ManyToManyField(Language, verbose_name=_('allowed languages'),
help_text=_('List of allowed submission languages.'))
is_public = models.BooleanField(verbose_name=_('publicly visible'), db_index=True, default=False)
is_manually_managed = models.BooleanField(verbose_name=_('manually managed'), db_index=True, default=False,
help_text=_('Whether judges should be allowed to manage data or not.'))
date = models.DateTimeField(verbose_name=_('date of publishing'), null=True, blank=True, db_index=True,
help_text=_("Doesn't have magic ability to auto-publish due to backward compatibility"))
banned_users = models.ManyToManyField(Profile, verbose_name=_('personae non gratae'), blank=True,
help_text=_('Bans the selected users from submitting to this problem.'))
license = models.ForeignKey(License, null=True, blank=True, on_delete=SET_NULL,
help_text=_('The license under which this problem is published.'))
og_image = models.CharField(verbose_name=_('OpenGraph image'), max_length=150, blank=True)
summary = models.TextField(blank=True, verbose_name=_('problem summary'),
help_text=_('Plain-text, shown in meta description tag, e.g. for social media.'))
user_count = models.IntegerField(verbose_name=_('number of users'), default=0,
help_text=_('The number of users who solved the problem.'))
ac_rate = models.FloatField(verbose_name=_('solve rate'), default=0)
points = models.FloatField(
verbose_name=_("points"),
help_text=_(
"Points awarded for problem completion. "
"Points are displayed with a 'p' suffix if partial."
),
validators=[MinValueValidator(settings.DMOJ_PROBLEM_MIN_PROBLEM_POINTS)],
)
partial = models.BooleanField(
verbose_name=_("allows partial points"), default=False
)
allowed_languages = models.ManyToManyField(
Language,
verbose_name=_("allowed languages"),
help_text=_("List of allowed submission languages."),
)
is_public = models.BooleanField(
verbose_name=_("publicly visible"), db_index=True, default=False
)
is_manually_managed = models.BooleanField(
verbose_name=_("manually managed"),
db_index=True,
default=False,
help_text=_("Whether judges should be allowed to manage data or not."),
)
date = models.DateTimeField(
verbose_name=_("date of publishing"),
null=True,
blank=True,
db_index=True,
help_text=_(
"Doesn't have magic ability to auto-publish due to backward compatibility"
),
)
banned_users = models.ManyToManyField(
Profile,
verbose_name=_("personae non gratae"),
blank=True,
help_text=_("Bans the selected users from submitting to this problem."),
)
license = models.ForeignKey(
License,
null=True,
blank=True,
on_delete=SET_NULL,
help_text=_("The license under which this problem is published."),
)
og_image = models.CharField(
verbose_name=_("OpenGraph image"), max_length=150, blank=True
)
summary = models.TextField(
blank=True,
verbose_name=_("problem summary"),
help_text=_(
"Plain-text, shown in meta description tag, e.g. for social media."
),
)
user_count = models.IntegerField(
verbose_name=_("number of users"),
default=0,
help_text=_("The number of users who solved the problem."),
)
ac_rate = models.FloatField(verbose_name=_("solve rate"), default=0)
objects = TranslatedProblemQuerySet.as_manager()
tickets = GenericRelation('Ticket')
tickets = GenericRelation("Ticket")
organizations = models.ManyToManyField(Organization, blank=True, verbose_name=_('organizations'),
help_text=_('If private, only these organizations may see the problem.'))
is_organization_private = models.BooleanField(verbose_name=_('private to organizations'), default=False)
organizations = models.ManyToManyField(
Organization,
blank=True,
verbose_name=_("organizations"),
help_text=_("If private, only these organizations may see the problem."),
)
is_organization_private = models.BooleanField(
verbose_name=_("private to organizations"), default=False
)
def __init__(self, *args, **kwargs):
super(Problem, self).__init__(*args, **kwargs)
@ -165,20 +308,30 @@ class Problem(models.Model):
@cached_property
def types_list(self):
return list(map(user_gettext, map(attrgetter('full_name'), self.types.all())))
return list(map(user_gettext, map(attrgetter("full_name"), self.types.all())))
def languages_list(self):
return self.allowed_languages.values_list('common_name', flat=True).distinct().order_by('common_name')
return (
self.allowed_languages.values_list("common_name", flat=True)
.distinct()
.order_by("common_name")
)
def is_editor(self, profile):
return (self.authors.filter(id=profile.id) | self.curators.filter(id=profile.id)).exists()
return (
self.authors.filter(id=profile.id) | self.curators.filter(id=profile.id)
).exists()
def is_editable_by(self, user):
if not user.is_authenticated:
return False
if user.has_perm('judge.edit_all_problem') or user.has_perm('judge.edit_public_problem') and self.is_public:
if (
user.has_perm("judge.edit_all_problem")
or user.has_perm("judge.edit_public_problem")
and self.is_public
):
return True
return user.has_perm('judge.edit_own_problem') and self.is_editor(user.profile)
return user.has_perm("judge.edit_own_problem") and self.is_editor(user.profile)
def is_accessible_by(self, user):
# Problem is public.
@ -188,23 +341,24 @@ class Problem(models.Model):
return True
# If the user can see all organization private problems.
if user.has_perm('judge.see_organization_problem'):
if user.has_perm("judge.see_organization_problem"):
return True
# If the user is in the organization.
if user.is_authenticated and \
self.organizations.filter(id__in=user.profile.organizations.all()):
if user.is_authenticated and self.organizations.filter(
id__in=user.profile.organizations.all()
):
return True
# If the user can view all problems.
if user.has_perm('judge.see_private_problem'):
if user.has_perm("judge.see_private_problem"):
return True
if not user.is_authenticated:
return False
# If the user authored the problem or is a curator.
if user.has_perm('judge.edit_own_problem') and self.is_editor(user.profile):
if user.has_perm("judge.edit_own_problem") and self.is_editor(user.profile):
return True
# If user is a tester.
@ -216,11 +370,18 @@ class Problem(models.Model):
if current is None:
return False
from judge.models import ContestProblem
return ContestProblem.objects.filter(problem_id=self.id, contest__users__id=current).exists()
return ContestProblem.objects.filter(
problem_id=self.id, contest__users__id=current
).exists()
def is_subs_manageable_by(self, user):
return user.is_staff and user.has_perm('judge.rejudge_submission') and self.is_editable_by(user)
return (
user.is_staff
and user.has_perm("judge.rejudge_submission")
and self.is_editable_by(user)
)
@classmethod
def get_visible_problems(cls, user):
# Do unauthenticated check here so we can skip authentication checks later on.
@ -235,15 +396,18 @@ class Problem(models.Model):
# - is_public problems
# - not is_organization_private or in organization or `judge.see_organization_problem`
# - author or curator or tester
queryset = cls.objects.defer('description')
queryset = cls.objects.defer("description")
if not (user.has_perm('judge.see_private_problem') or user.has_perm('judge.edit_all_problem')):
if not (
user.has_perm("judge.see_private_problem")
or user.has_perm("judge.edit_all_problem")
):
q = Q(is_public=True)
if not user.has_perm('judge.see_organization_problem'):
if not user.has_perm("judge.see_organization_problem"):
# Either not organization private or in the organization.
q &= (
Q(is_organization_private=False) |
Q(is_organization_private=True, organizations__in=user.profile.organizations.all())
q &= Q(is_organization_private=False) | Q(
is_organization_private=True,
organizations__in=user.profile.organizations.all(),
)
# Authors, curators, and testers should always have access, so OR at the very end.
@ -256,40 +420,46 @@ class Problem(models.Model):
@classmethod
def get_public_problems(cls):
return cls.objects.filter(is_public=True, is_organization_private=False).defer('description')
return cls.objects.filter(is_public=True, is_organization_private=False).defer(
"description"
)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('problem_detail', args=(self.code,))
return reverse("problem_detail", args=(self.code,))
@cached_property
def author_ids(self):
return self.authors.values_list('id', flat=True)
return self.authors.values_list("id", flat=True)
@cached_property
def editor_ids(self):
return self.author_ids | self.curators.values_list('id', flat=True)
return self.author_ids | self.curators.values_list("id", flat=True)
@cached_property
def tester_ids(self):
return self.testers.values_list('id', flat=True)
return self.testers.values_list("id", flat=True)
@cached_property
def usable_common_names(self):
return set(self.usable_languages.values_list('common_name', flat=True))
return set(self.usable_languages.values_list("common_name", flat=True))
@property
def usable_languages(self):
return self.allowed_languages.filter(judges__in=self.judges.filter(online=True)).distinct()
return self.allowed_languages.filter(
judges__in=self.judges.filter(online=True)
).distinct()
def translated_name(self, language):
if language in self._translated_name_cache:
return self._translated_name_cache[language]
# Hits database despite prefetch_related.
try:
name = self.translations.filter(language=language).values_list('name', flat=True)[0]
name = self.translations.filter(language=language).values_list(
"name", flat=True
)[0]
except IndexError:
name = self.name
self._translated_name_cache[language] = name
@ -310,12 +480,23 @@ class Problem(models.Model):
return ProblemClarification.objects.filter(problem=self)
def update_stats(self):
self.user_count = self.submission_set.filter(points__gte=self.points, result='AC',
user__is_unlisted=False).values('user').distinct().count()
self.user_count = (
self.submission_set.filter(
points__gte=self.points, result="AC", user__is_unlisted=False
)
.values("user")
.distinct()
.count()
)
submissions = self.submission_set.count()
if submissions:
self.ac_rate = 100.0 * self.submission_set.filter(points__gte=self.points, result='AC',
user__is_unlisted=False).count() / submissions
self.ac_rate = (
100.0
* self.submission_set.filter(
points__gte=self.points, result="AC", user__is_unlisted=False
).count()
/ submissions
)
else:
self.ac_rate = 0
self.save()
@ -324,9 +505,13 @@ class Problem(models.Model):
def _get_limits(self, key):
global_limit = getattr(self, key)
limits = {limit['language_id']: (limit['language__name'], limit[key])
for limit in self.language_limits.values('language_id', 'language__name', key)
if limit[key] != global_limit}
limits = {
limit["language_id"]: (limit["language__name"], limit[key])
for limit in self.language_limits.values(
"language_id", "language__name", key
)
if limit[key] != global_limit
}
limit_ids = set(limits.keys())
common = []
@ -346,21 +531,21 @@ class Problem(models.Model):
@property
def language_time_limit(self):
key = 'problem_tls:%d' % self.id
key = "problem_tls:%d" % self.id
result = cache.get(key)
if result is not None:
return result
result = self._get_limits('time_limit')
result = self._get_limits("time_limit")
cache.set(key, result)
return result
@property
def language_memory_limit(self):
key = 'problem_mls:%d' % self.id
key = "problem_mls:%d" % self.id
result = cache.get(key)
if result is not None:
return result
result = self._get_limits('memory_limit')
result = self._get_limits("memory_limit")
cache.set(key, result)
return result
@ -395,105 +580,143 @@ class Problem(models.Model):
return False
# If the user has a full AC submission to the problem (solved the problem).
return self.submission_set.filter(user=user.profile, result='AC', points=F('problem__points')).exists()
return self.submission_set.filter(
user=user.profile, result="AC", points=F("problem__points")
).exists()
class Meta:
permissions = (
('see_private_problem', 'See hidden problems'),
('edit_own_problem', 'Edit own problems'),
('edit_all_problem', 'Edit all problems'),
('edit_public_problem', 'Edit all public problems'),
('clone_problem', 'Clone problem'),
('change_public_visibility', 'Change is_public field'),
('change_manually_managed', 'Change is_manually_managed field'),
('see_organization_problem', 'See organization-private problems'),
('suggest_problem_changes', 'Suggest changes to problem'),
("see_private_problem", "See hidden problems"),
("edit_own_problem", "Edit own problems"),
("edit_all_problem", "Edit all problems"),
("edit_public_problem", "Edit all public problems"),
("clone_problem", "Clone problem"),
("change_public_visibility", "Change is_public field"),
("change_manually_managed", "Change is_manually_managed field"),
("see_organization_problem", "See organization-private problems"),
("suggest_problem_changes", "Suggest changes to problem"),
)
verbose_name = _('problem')
verbose_name_plural = _('problems')
verbose_name = _("problem")
verbose_name_plural = _("problems")
class ProblemTranslation(models.Model):
problem = models.ForeignKey(Problem, verbose_name=_('problem'), related_name='translations', on_delete=CASCADE)
language = models.CharField(verbose_name=_('language'), max_length=7, choices=settings.LANGUAGES)
name = models.CharField(verbose_name=_('translated name'), max_length=100, db_index=True)
description = models.TextField(verbose_name=_('translated description'))
problem = models.ForeignKey(
Problem,
verbose_name=_("problem"),
related_name="translations",
on_delete=CASCADE,
)
language = models.CharField(
verbose_name=_("language"), max_length=7, choices=settings.LANGUAGES
)
name = models.CharField(
verbose_name=_("translated name"), max_length=100, db_index=True
)
description = models.TextField(verbose_name=_("translated description"))
class Meta:
unique_together = ('problem', 'language')
verbose_name = _('problem translation')
verbose_name_plural = _('problem translations')
unique_together = ("problem", "language")
verbose_name = _("problem translation")
verbose_name_plural = _("problem translations")
class ProblemClarification(models.Model):
problem = models.ForeignKey(Problem, verbose_name=_('clarified problem'), on_delete=CASCADE)
description = models.TextField(verbose_name=_('clarification body'))
date = models.DateTimeField(verbose_name=_('clarification timestamp'), auto_now_add=True)
problem = models.ForeignKey(
Problem, verbose_name=_("clarified problem"), on_delete=CASCADE
)
description = models.TextField(verbose_name=_("clarification body"))
date = models.DateTimeField(
verbose_name=_("clarification timestamp"), auto_now_add=True
)
class LanguageLimit(models.Model):
problem = models.ForeignKey(Problem, verbose_name=_('problem'), related_name='language_limits', on_delete=CASCADE)
language = models.ForeignKey(Language, verbose_name=_('language'), on_delete=CASCADE)
time_limit = models.FloatField(verbose_name=_('time limit'),
validators=[MinValueValidator(settings.DMOJ_PROBLEM_MIN_TIME_LIMIT),
MaxValueValidator(settings.DMOJ_PROBLEM_MAX_TIME_LIMIT)])
memory_limit = models.IntegerField(verbose_name=_('memory limit'),
validators=[MinValueValidator(settings.DMOJ_PROBLEM_MIN_MEMORY_LIMIT),
MaxValueValidator(settings.DMOJ_PROBLEM_MAX_MEMORY_LIMIT)])
problem = models.ForeignKey(
Problem,
verbose_name=_("problem"),
related_name="language_limits",
on_delete=CASCADE,
)
language = models.ForeignKey(
Language, verbose_name=_("language"), on_delete=CASCADE
)
time_limit = models.FloatField(
verbose_name=_("time limit"),
validators=[
MinValueValidator(settings.DMOJ_PROBLEM_MIN_TIME_LIMIT),
MaxValueValidator(settings.DMOJ_PROBLEM_MAX_TIME_LIMIT),
],
)
memory_limit = models.IntegerField(
verbose_name=_("memory limit"),
validators=[
MinValueValidator(settings.DMOJ_PROBLEM_MIN_MEMORY_LIMIT),
MaxValueValidator(settings.DMOJ_PROBLEM_MAX_MEMORY_LIMIT),
],
)
class Meta:
unique_together = ('problem', 'language')
verbose_name = _('language-specific resource limit')
verbose_name_plural = _('language-specific resource limits')
unique_together = ("problem", "language")
verbose_name = _("language-specific resource limit")
verbose_name_plural = _("language-specific resource limits")
class Solution(models.Model):
problem = models.OneToOneField(Problem, on_delete=SET_NULL, verbose_name=_('associated problem'),
null=True, blank=True, related_name='solution')
is_public = models.BooleanField(verbose_name=_('public visibility'), default=False)
publish_on = models.DateTimeField(verbose_name=_('publish date'))
authors = models.ManyToManyField(Profile, verbose_name=_('authors'), blank=True)
content = models.TextField(verbose_name=_('editorial content'))
problem = models.OneToOneField(
Problem,
on_delete=SET_NULL,
verbose_name=_("associated problem"),
null=True,
blank=True,
related_name="solution",
)
is_public = models.BooleanField(verbose_name=_("public visibility"), default=False)
publish_on = models.DateTimeField(verbose_name=_("publish date"))
authors = models.ManyToManyField(Profile, verbose_name=_("authors"), blank=True)
content = models.TextField(verbose_name=_("editorial content"))
def get_absolute_url(self):
problem = self.problem
if problem is None:
return reverse('home')
return reverse("home")
else:
return reverse('problem_editorial', args=[problem.code])
return reverse("problem_editorial", args=[problem.code])
def __str__(self):
return _('Editorial for %s') % self.problem.name
return _("Editorial for %s") % self.problem.name
class Meta:
permissions = (
('see_private_solution', 'See hidden solutions'),
)
verbose_name = _('solution')
verbose_name_plural = _('solutions')
permissions = (("see_private_solution", "See hidden solutions"),)
verbose_name = _("solution")
verbose_name_plural = _("solutions")
class ProblemPointsVote(models.Model):
points = models.IntegerField(
verbose_name=_('proposed point value'),
help_text=_('The amount of points you think this problem deserves.'),
verbose_name=_("proposed point value"),
help_text=_("The amount of points you think this problem deserves."),
validators=[
MinValueValidator(100),
MaxValueValidator(600),
],
)
voter = models.ForeignKey(Profile, related_name='problem_points_votes', on_delete=CASCADE, db_index=True)
problem = models.ForeignKey(Problem, related_name='problem_points_votes', on_delete=CASCADE, db_index=True)
voter = models.ForeignKey(
Profile, related_name="problem_points_votes", on_delete=CASCADE, db_index=True
)
problem = models.ForeignKey(
Problem, related_name="problem_points_votes", on_delete=CASCADE, db_index=True
)
vote_time = models.DateTimeField(
verbose_name=_('The time this vote was cast'),
verbose_name=_("The time this vote was cast"),
auto_now_add=True,
blank=True,
)
class Meta:
verbose_name = _('vote')
verbose_name_plural = _('votes')
verbose_name = _("vote")
verbose_name_plural = _("votes")
def __str__(self):
return f'{self.voter}: {self.points} for {self.problem.code}'
return f"{self.voter}: {self.points} for {self.problem.code}"