NDOJ/judge/views/status.py

125 lines
3.5 KiB
Python
Raw Normal View History

2020-01-21 06:35:58 +00:00
from collections import defaultdict
from functools import partial
from django.shortcuts import render
from django.utils.translation import gettext as _
from packaging import version
from judge.models import Judge, Language, RuntimeVersion
2022-05-14 17:57:27 +00:00
__all__ = ["status_all", "status_table"]
2020-01-21 06:35:58 +00:00
def get_judges(request):
if request.user.is_superuser or request.user.is_staff:
2022-05-14 17:57:27 +00:00
return True, Judge.objects.order_by("-online", "name")
2020-01-21 06:35:58 +00:00
else:
return False, Judge.objects.filter(online=True)
def status_all(request):
see_all, judges = get_judges(request)
2022-05-14 17:57:27 +00:00
return render(
request,
"status/judge-status.html",
{
"title": _("Status"),
"judges": judges,
"see_all_judges": see_all,
},
)
2020-01-21 06:35:58 +00:00
def status_table(request):
see_all, judges = get_judges(request)
2022-05-14 17:57:27 +00:00
return render(
request,
"status/judge-status-table.html",
{
"judges": judges,
"see_all_judges": see_all,
},
)
2020-01-21 06:35:58 +00:00
class LatestList(list):
2022-05-14 17:57:27 +00:00
__slots__ = ("versions", "is_latest")
2020-01-21 06:35:58 +00:00
def compare_version_list(x, y):
if sorted(x.keys()) != sorted(y.keys()):
return False
for k in x.keys():
if len(x[k]) != len(y[k]):
return False
for a, b in zip(x[k], y[k]):
if a.name != b.name:
return False
if a.version != b.version:
return False
return True
def version_matrix(request):
matrix = defaultdict(partial(defaultdict, LatestList))
latest = defaultdict(list)
groups = defaultdict(list)
judges = {judge.id: judge.name for judge in Judge.objects.filter(online=True)}
languages = Language.objects.filter(judges__online=True).distinct()
2022-05-14 17:57:27 +00:00
for runtime in RuntimeVersion.objects.filter(judge__online=True).order_by(
"priority"
):
2020-01-21 06:35:58 +00:00
matrix[runtime.judge_id][runtime.language_id].append(runtime)
2022-11-01 01:43:06 +00:00
for judge, data in matrix.items():
2022-05-14 17:57:27 +00:00
name_tuple = judges[judge].rpartition(".")
2020-01-21 06:35:58 +00:00
groups[name_tuple[0] or name_tuple[-1]].append((judges[judge], data))
matrix = {}
2022-11-01 01:43:06 +00:00
for group, data in groups.items():
2020-01-21 06:35:58 +00:00
if len(data) == 1:
judge, data = data[0]
matrix[judge] = data
continue
ds = list(range(len(data)))
size = [1] * len(data)
for i, (p, x) in enumerate(data):
if ds[i] != i:
continue
for j, (q, y) in enumerate(data):
if i != j and compare_version_list(x, y):
ds[j] = i
size[i] += 1
size[j] = 0
rep = max(range(len(data)), key=size.__getitem__)
matrix[group] = data[rep][1]
for i, (j, x) in enumerate(data):
if ds[i] != rep:
matrix[j] = x
2022-11-01 01:43:06 +00:00
for data in matrix.values():
for language, versions in data.items():
2020-01-21 06:35:58 +00:00
versions.versions = [version.parse(runtime.version) for runtime in versions]
if versions.versions > latest[language]:
latest[language] = versions.versions
2022-11-01 01:43:06 +00:00
for data in matrix.values():
for language, versions in data.items():
2020-01-21 06:35:58 +00:00
versions.is_latest = versions.versions == latest[language]
languages = sorted(languages, key=lambda lang: version.parse(lang.name))
2022-05-14 17:57:27 +00:00
return render(
request,
"status/versions.html",
{
"title": _("Version matrix"),
"judges": sorted(matrix.keys()),
"languages": languages,
"matrix": matrix,
},
)