112 lines
3.4 KiB
Python
112 lines
3.4 KiB
Python
|
from collections import defaultdict
|
||
|
from functools import partial
|
||
|
|
||
|
from django.shortcuts import render
|
||
|
from django.utils import six
|
||
|
from django.utils.translation import gettext as _
|
||
|
from packaging import version
|
||
|
|
||
|
from judge.models import Judge, Language, RuntimeVersion
|
||
|
|
||
|
__all__ = ['status_all', 'status_table']
|
||
|
|
||
|
|
||
|
def get_judges(request):
|
||
|
if request.user.is_superuser or request.user.is_staff:
|
||
|
return True, Judge.objects.order_by('-online', 'name')
|
||
|
else:
|
||
|
return False, Judge.objects.filter(online=True)
|
||
|
|
||
|
|
||
|
def status_all(request):
|
||
|
see_all, judges = get_judges(request)
|
||
|
return render(request, 'status/judge-status.html', {
|
||
|
'title': _('Status'),
|
||
|
'judges': judges,
|
||
|
'see_all_judges': see_all,
|
||
|
})
|
||
|
|
||
|
|
||
|
def status_table(request):
|
||
|
see_all, judges = get_judges(request)
|
||
|
return render(request, 'status/judge-status-table.html', {
|
||
|
'judges': judges,
|
||
|
'see_all_judges': see_all,
|
||
|
})
|
||
|
|
||
|
|
||
|
class LatestList(list):
|
||
|
__slots__ = ('versions', 'is_latest')
|
||
|
|
||
|
|
||
|
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()
|
||
|
|
||
|
for runtime in RuntimeVersion.objects.filter(judge__online=True).order_by('priority'):
|
||
|
matrix[runtime.judge_id][runtime.language_id].append(runtime)
|
||
|
|
||
|
for judge, data in six.iteritems(matrix):
|
||
|
name_tuple = judges[judge].rpartition('.')
|
||
|
groups[name_tuple[0] or name_tuple[-1]].append((judges[judge], data))
|
||
|
|
||
|
matrix = {}
|
||
|
for group, data in six.iteritems(groups):
|
||
|
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
|
||
|
|
||
|
for data in six.itervalues(matrix):
|
||
|
for language, versions in six.iteritems(data):
|
||
|
versions.versions = [version.parse(runtime.version) for runtime in versions]
|
||
|
if versions.versions > latest[language]:
|
||
|
latest[language] = versions.versions
|
||
|
|
||
|
for data in six.itervalues(matrix):
|
||
|
for language, versions in six.iteritems(data):
|
||
|
versions.is_latest = versions.versions == latest[language]
|
||
|
|
||
|
languages = sorted(languages, key=lambda lang: version.parse(lang.name))
|
||
|
return render(request, 'status/versions.html', {
|
||
|
'title': _('Version matrix'),
|
||
|
'judges': sorted(matrix.keys()),
|
||
|
'languages': languages,
|
||
|
'matrix': matrix,
|
||
|
})
|