Reformat using black
This commit is contained in:
parent
efee4ad081
commit
a87fb49918
221 changed files with 19127 additions and 7310 deletions
|
@ -12,38 +12,82 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
from judge.judgeapi import disconnect_judge
|
||||
|
||||
__all__ = ['Language', 'RuntimeVersion', 'Judge']
|
||||
__all__ = ["Language", "RuntimeVersion", "Judge"]
|
||||
|
||||
|
||||
class Language(models.Model):
|
||||
key = models.CharField(max_length=6, verbose_name=_('short identifier'),
|
||||
help_text=_('The identifier for this language; the same as its executor id for judges.'),
|
||||
unique=True)
|
||||
name = models.CharField(max_length=20, verbose_name=_('long name'),
|
||||
help_text=_('Longer name for the language, e.g. "Python 2" or "C++11".'))
|
||||
short_name = models.CharField(max_length=10, verbose_name=_('short name'),
|
||||
help_text=_('More readable, but short, name to display publicly; e.g. "PY2" or '
|
||||
'"C++11". If left blank, it will default to the '
|
||||
'short identifier.'),
|
||||
null=True, blank=True)
|
||||
common_name = models.CharField(max_length=10, verbose_name=_('common name'),
|
||||
help_text=_('Common name for the language. For example, the common name for C++03, '
|
||||
'C++11, and C++14 would be "C++"'))
|
||||
ace = models.CharField(max_length=20, verbose_name=_('ace mode name'),
|
||||
help_text=_('Language ID for Ace.js editor highlighting, appended to "mode-" to determine '
|
||||
'the Ace JavaScript file to use, e.g., "python".'))
|
||||
pygments = models.CharField(max_length=20, verbose_name=_('pygments name'),
|
||||
help_text=_('Language ID for Pygments highlighting in source windows.'))
|
||||
template = models.TextField(verbose_name=_('code template'),
|
||||
help_text=_('Code template to display in submission editor.'), blank=True)
|
||||
info = models.CharField(max_length=50, verbose_name=_('runtime info override'), blank=True,
|
||||
help_text=_("Do not set this unless you know what you're doing! It will override the "
|
||||
"usually more specific, judge-provided runtime info!"))
|
||||
description = models.TextField(verbose_name=_('language description'),
|
||||
help_text=_('Use this field to inform users of quirks with your environment, '
|
||||
'additional restrictions, etc.'), blank=True)
|
||||
extension = models.CharField(max_length=10, verbose_name=_('extension'),
|
||||
help_text=_('The extension of source files, e.g., "py" or "cpp".'))
|
||||
key = models.CharField(
|
||||
max_length=6,
|
||||
verbose_name=_("short identifier"),
|
||||
help_text=_(
|
||||
"The identifier for this language; the same as its executor id for judges."
|
||||
),
|
||||
unique=True,
|
||||
)
|
||||
name = models.CharField(
|
||||
max_length=20,
|
||||
verbose_name=_("long name"),
|
||||
help_text=_('Longer name for the language, e.g. "Python 2" or "C++11".'),
|
||||
)
|
||||
short_name = models.CharField(
|
||||
max_length=10,
|
||||
verbose_name=_("short name"),
|
||||
help_text=_(
|
||||
'More readable, but short, name to display publicly; e.g. "PY2" or '
|
||||
'"C++11". If left blank, it will default to the '
|
||||
"short identifier."
|
||||
),
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
common_name = models.CharField(
|
||||
max_length=10,
|
||||
verbose_name=_("common name"),
|
||||
help_text=_(
|
||||
"Common name for the language. For example, the common name for C++03, "
|
||||
'C++11, and C++14 would be "C++"'
|
||||
),
|
||||
)
|
||||
ace = models.CharField(
|
||||
max_length=20,
|
||||
verbose_name=_("ace mode name"),
|
||||
help_text=_(
|
||||
'Language ID for Ace.js editor highlighting, appended to "mode-" to determine '
|
||||
'the Ace JavaScript file to use, e.g., "python".'
|
||||
),
|
||||
)
|
||||
pygments = models.CharField(
|
||||
max_length=20,
|
||||
verbose_name=_("pygments name"),
|
||||
help_text=_("Language ID for Pygments highlighting in source windows."),
|
||||
)
|
||||
template = models.TextField(
|
||||
verbose_name=_("code template"),
|
||||
help_text=_("Code template to display in submission editor."),
|
||||
blank=True,
|
||||
)
|
||||
info = models.CharField(
|
||||
max_length=50,
|
||||
verbose_name=_("runtime info override"),
|
||||
blank=True,
|
||||
help_text=_(
|
||||
"Do not set this unless you know what you're doing! It will override the "
|
||||
"usually more specific, judge-provided runtime info!"
|
||||
),
|
||||
)
|
||||
description = models.TextField(
|
||||
verbose_name=_("language description"),
|
||||
help_text=_(
|
||||
"Use this field to inform users of quirks with your environment, "
|
||||
"additional restrictions, etc."
|
||||
),
|
||||
blank=True,
|
||||
)
|
||||
extension = models.CharField(
|
||||
max_length=10,
|
||||
verbose_name=_("extension"),
|
||||
help_text=_('The extension of source files, e.g., "py" or "cpp".'),
|
||||
)
|
||||
|
||||
def runtime_versions(self):
|
||||
runtimes = OrderedDict()
|
||||
|
@ -52,25 +96,29 @@ class Language(models.Model):
|
|||
id = runtime.name
|
||||
if id not in runtimes:
|
||||
runtimes[id] = set()
|
||||
if not runtime.version: # empty str == error determining version on judge side
|
||||
if (
|
||||
not runtime.version
|
||||
): # empty str == error determining version on judge side
|
||||
continue
|
||||
runtimes[id].add(runtime.version)
|
||||
|
||||
lang_versions = []
|
||||
for id, version_list in runtimes.items():
|
||||
lang_versions.append((id, sorted(version_list, key=lambda a: tuple(map(int, a.split('.'))))))
|
||||
lang_versions.append(
|
||||
(id, sorted(version_list, key=lambda a: tuple(map(int, a.split(".")))))
|
||||
)
|
||||
return lang_versions
|
||||
|
||||
@classmethod
|
||||
def get_common_name_map(cls):
|
||||
result = cache.get('lang:cn_map')
|
||||
result = cache.get("lang:cn_map")
|
||||
if result is not None:
|
||||
return result
|
||||
result = defaultdict(set)
|
||||
for id, cn in Language.objects.values_list('id', 'common_name'):
|
||||
for id, cn in Language.objects.values_list("id", "common_name"):
|
||||
result[cn].add(id)
|
||||
result = {id: cns for id, cns in result.items() if len(cns) > 1}
|
||||
cache.set('lang:cn_map', result, 86400)
|
||||
cache.set("lang:cn_map", result, 86400)
|
||||
return result
|
||||
|
||||
@cached_property
|
||||
|
@ -83,17 +131,19 @@ class Language(models.Model):
|
|||
@cached_property
|
||||
def display_name(self):
|
||||
if self.info:
|
||||
return '%s (%s)' % (self.name, self.info)
|
||||
return "%s (%s)" % (self.name, self.info)
|
||||
else:
|
||||
return self.name
|
||||
|
||||
@classmethod
|
||||
def get_python3(cls):
|
||||
# We really need a default language, and this app is in Python 3
|
||||
return Language.objects.get_or_create(key='PY3', defaults={'name': 'Python 3'})[0]
|
||||
return Language.objects.get_or_create(key="PY3", defaults={"name": "Python 3"})[
|
||||
0
|
||||
]
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('runtime_list') + '#' + self.key
|
||||
return reverse("runtime_list") + "#" + self.key
|
||||
|
||||
@classmethod
|
||||
def get_default_language(cls):
|
||||
|
@ -107,36 +157,67 @@ class Language(models.Model):
|
|||
return cls.get_default_language().pk
|
||||
|
||||
class Meta:
|
||||
ordering = ['key']
|
||||
verbose_name = _('language')
|
||||
verbose_name_plural = _('languages')
|
||||
ordering = ["key"]
|
||||
verbose_name = _("language")
|
||||
verbose_name_plural = _("languages")
|
||||
|
||||
|
||||
class RuntimeVersion(models.Model):
|
||||
language = models.ForeignKey(Language, verbose_name=_('language to which this runtime belongs'), on_delete=CASCADE)
|
||||
judge = models.ForeignKey('Judge', verbose_name=_('judge on which this runtime exists'), on_delete=CASCADE)
|
||||
name = models.CharField(max_length=64, verbose_name=_('runtime name'))
|
||||
version = models.CharField(max_length=64, verbose_name=_('runtime version'), blank=True)
|
||||
priority = models.IntegerField(verbose_name=_('order in which to display this runtime'), default=0)
|
||||
language = models.ForeignKey(
|
||||
Language,
|
||||
verbose_name=_("language to which this runtime belongs"),
|
||||
on_delete=CASCADE,
|
||||
)
|
||||
judge = models.ForeignKey(
|
||||
"Judge", verbose_name=_("judge on which this runtime exists"), on_delete=CASCADE
|
||||
)
|
||||
name = models.CharField(max_length=64, verbose_name=_("runtime name"))
|
||||
version = models.CharField(
|
||||
max_length=64, verbose_name=_("runtime version"), blank=True
|
||||
)
|
||||
priority = models.IntegerField(
|
||||
verbose_name=_("order in which to display this runtime"), default=0
|
||||
)
|
||||
|
||||
|
||||
class Judge(models.Model):
|
||||
name = models.CharField(max_length=50, help_text=_('Server name, hostname-style'), unique=True)
|
||||
created = models.DateTimeField(auto_now_add=True, verbose_name=_('time of creation'))
|
||||
auth_key = models.CharField(max_length=100, help_text=_('A key to authenticate this judge'),
|
||||
verbose_name=_('authentication key'))
|
||||
is_blocked = models.BooleanField(verbose_name=_('block judge'), default=False,
|
||||
help_text=_('Whether this judge should be blocked from connecting, '
|
||||
'even if its key is correct.'))
|
||||
online = models.BooleanField(verbose_name=_('judge online status'), default=False)
|
||||
start_time = models.DateTimeField(verbose_name=_('judge start time'), null=True)
|
||||
ping = models.FloatField(verbose_name=_('response time'), null=True)
|
||||
load = models.FloatField(verbose_name=_('system load'), null=True,
|
||||
help_text=_('Load for the last minute, divided by processors to be fair.'))
|
||||
description = models.TextField(blank=True, verbose_name=_('description'))
|
||||
last_ip = models.GenericIPAddressField(verbose_name='Last connected IP', blank=True, null=True)
|
||||
problems = models.ManyToManyField('Problem', verbose_name=_('problems'), related_name='judges')
|
||||
runtimes = models.ManyToManyField(Language, verbose_name=_('judges'), related_name='judges')
|
||||
name = models.CharField(
|
||||
max_length=50, help_text=_("Server name, hostname-style"), unique=True
|
||||
)
|
||||
created = models.DateTimeField(
|
||||
auto_now_add=True, verbose_name=_("time of creation")
|
||||
)
|
||||
auth_key = models.CharField(
|
||||
max_length=100,
|
||||
help_text=_("A key to authenticate this judge"),
|
||||
verbose_name=_("authentication key"),
|
||||
)
|
||||
is_blocked = models.BooleanField(
|
||||
verbose_name=_("block judge"),
|
||||
default=False,
|
||||
help_text=_(
|
||||
"Whether this judge should be blocked from connecting, "
|
||||
"even if its key is correct."
|
||||
),
|
||||
)
|
||||
online = models.BooleanField(verbose_name=_("judge online status"), default=False)
|
||||
start_time = models.DateTimeField(verbose_name=_("judge start time"), null=True)
|
||||
ping = models.FloatField(verbose_name=_("response time"), null=True)
|
||||
load = models.FloatField(
|
||||
verbose_name=_("system load"),
|
||||
null=True,
|
||||
help_text=_("Load for the last minute, divided by processors to be fair."),
|
||||
)
|
||||
description = models.TextField(blank=True, verbose_name=_("description"))
|
||||
last_ip = models.GenericIPAddressField(
|
||||
verbose_name="Last connected IP", blank=True, null=True
|
||||
)
|
||||
problems = models.ManyToManyField(
|
||||
"Problem", verbose_name=_("problems"), related_name="judges"
|
||||
)
|
||||
runtimes = models.ManyToManyField(
|
||||
Language, verbose_name=_("judges"), related_name="judges"
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
@ -148,22 +229,23 @@ class Judge(models.Model):
|
|||
|
||||
@cached_property
|
||||
def runtime_versions(self):
|
||||
qs = (self.runtimeversion_set.values('language__key', 'language__name', 'version', 'name')
|
||||
.order_by('language__key', 'priority'))
|
||||
qs = self.runtimeversion_set.values(
|
||||
"language__key", "language__name", "version", "name"
|
||||
).order_by("language__key", "priority")
|
||||
|
||||
ret = OrderedDict()
|
||||
|
||||
for data in qs:
|
||||
key = data['language__key']
|
||||
key = data["language__key"]
|
||||
if key not in ret:
|
||||
ret[key] = {'name': data['language__name'], 'runtime': []}
|
||||
ret[key]['runtime'].append((data['name'], (data['version'],)))
|
||||
ret[key] = {"name": data["language__name"], "runtime": []}
|
||||
ret[key]["runtime"].append((data["name"], (data["version"],)))
|
||||
|
||||
return list(ret.items())
|
||||
|
||||
@cached_property
|
||||
def uptime(self):
|
||||
return timezone.now() - self.start_time if self.online else 'N/A'
|
||||
return timezone.now() - self.start_time if self.online else "N/A"
|
||||
|
||||
@cached_property
|
||||
def ping_ms(self):
|
||||
|
@ -171,9 +253,9 @@ class Judge(models.Model):
|
|||
|
||||
@cached_property
|
||||
def runtime_list(self):
|
||||
return map(attrgetter('name'), self.runtimes.all())
|
||||
return map(attrgetter("name"), self.runtimes.all())
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
verbose_name = _('judge')
|
||||
verbose_name_plural = _('judges')
|
||||
ordering = ["name"]
|
||||
verbose_name = _("judge")
|
||||
verbose_name_plural = _("judges")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue