From 07d5ad221612915fe94281444d489e4416535737 Mon Sep 17 00:00:00 2001 From: cuom1999 Date: Mon, 2 Jan 2023 17:22:45 -0600 Subject: [PATCH] Make ioi16 related files cleaner --- judge/admin/contest.py | 4 +- judge/contest_format/base.py | 11 ++- judge/contest_format/new_ioi.py | 20 +++-- judge/migrations/0144_auto_20230103_0523.py | 28 +++++++ judge/models/contest.py | 6 +- judge/views/contests.py | 4 +- judge/views/resolver.py | 10 +-- judge/views/submission.py | 42 ++++++---- resources/base.scss | 2 +- resources/darkmode.css | 3 + templates/problem/list.html | 10 +-- templates/submission/list.html | 89 +++++++++++---------- templates/submission/row.html | 2 +- templates/submission/status-testcases.html | 6 +- 14 files changed, 145 insertions(+), 92 deletions(-) create mode 100644 judge/migrations/0144_auto_20230103_0523.py diff --git a/judge/admin/contest.py b/judge/admin/contest.py index a7441b0..3e257d4 100644 --- a/judge/admin/contest.py +++ b/judge/admin/contest.py @@ -68,7 +68,7 @@ class ContestProblemInlineForm(ModelForm): class Meta: widgets = { "problem": AdminHeavySelect2Widget(data_view="problem_select2"), - "frozen_subtasks": TextInput(attrs={"size": "3"}), + "hidden_subtasks": TextInput(attrs={"size": "3"}), "points": TextInput(attrs={"size": "1"}), "order": TextInput(attrs={"size": "1"}), "output_prefix_override": TextInput(attrs={"size": "1"}), @@ -85,7 +85,7 @@ class ContestProblemInline(admin.TabularInline): "partial", "is_pretested", "max_submissions", - "frozen_subtasks", + "hidden_subtasks", "output_prefix_override", "order", "rejudge_column", diff --git a/judge/contest_format/base.py b/judge/contest_format/base.py index 78673bf..e64e211 100644 --- a/judge/contest_format/base.py +++ b/judge/contest_format/base.py @@ -16,6 +16,9 @@ class BaseContestFormat(metaclass=ABCMeta): self.config = config self.contest = contest + # Use in ioi16 to display ranking with hidden subtasks + self.has_hidden_subtasks = False + @abstractproperty def name(self): """ @@ -98,9 +101,9 @@ class BaseContestFormat(metaclass=ABCMeta): return "partial-score" def handle_frozen_state(self, participation, format_data): - frozen_subtasks = {} - if hasattr(self, "get_frozen_subtasks"): - frozen_subtasks = self.get_frozen_subtasks() + hidden_subtasks = {} + if hasattr(self, "get_hidden_subtasks"): + hidden_subtasks = self.get_hidden_subtasks() queryset = participation.submissions.values("problem_id").annotate( time=Max("submission__date") @@ -113,7 +116,7 @@ class BaseContestFormat(metaclass=ABCMeta): and result["time"] >= self.contest.freeze_after + participation.start ) - if is_after_freeze or frozen_subtasks.get(problem): + if is_after_freeze or hidden_subtasks.get(problem): format_data[problem]["frozen"] = True else: format_data[problem] = {"time": 0, "points": 0, "frozen": True} diff --git a/judge/contest_format/new_ioi.py b/judge/contest_format/new_ioi.py index 73dcc84..758680f 100644 --- a/judge/contest_format/new_ioi.py +++ b/judge/contest_format/new_ioi.py @@ -14,14 +14,18 @@ class NewIOIContestFormat(IOIContestFormat): cumtime: Specify True if time penalties are to be computed. Defaults to False. """ - def get_frozen_subtasks(self): - queryset = self.contest.contest_problems.values_list("id", "frozen_subtasks") + def __init__(self, contest, config): + super().__init__(contest, config) + self.has_hidden_subtasks = True + + def get_hidden_subtasks(self): + queryset = self.contest.contest_problems.values_list("id", "hidden_subtasks") res = {} - for problem_id, frozen_subtasks in queryset: + for problem_id, hidden_subtasks in queryset: subtasks = set() - if frozen_subtasks: - frozen_subtasks = frozen_subtasks.split(",") - for i in frozen_subtasks: + if hidden_subtasks: + hidden_subtasks = hidden_subtasks.split(",") + for i in hidden_subtasks: try: subtasks.add(int(i)) except Exception as e: @@ -100,7 +104,7 @@ class NewIOIContestFormat(IOIContestFormat): return cursor.fetchall() def update_participation(self, participation): - frozen_subtasks = self.get_frozen_subtasks() + hidden_subtasks = self.get_hidden_subtasks() def calculate_format_data(participation, include_frozen): format_data = {} @@ -127,7 +131,7 @@ class NewIOIContestFormat(IOIContestFormat): "total_points": 0, } if ( - subtask not in frozen_subtasks.get(problem_id, set()) + subtask not in hidden_subtasks.get(problem_id, set()) or include_frozen ): format_data[problem_id]["points"] += subtask_points diff --git a/judge/migrations/0144_auto_20230103_0523.py b/judge/migrations/0144_auto_20230103_0523.py new file mode 100644 index 0000000..97f6234 --- /dev/null +++ b/judge/migrations/0144_auto_20230103_0523.py @@ -0,0 +1,28 @@ +# Generated by Django 3.2.16 on 2023-01-02 22:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("judge", "0143_auto_20221229_0153"), + ] + + operations = [ + migrations.RemoveField( + model_name="contestproblem", + name="frozen_subtasks", + ), + migrations.AddField( + model_name="contestproblem", + name="hidden_subtasks", + field=models.CharField( + blank=True, + help_text="Separated by commas, e.g: 2, 3", + max_length=20, + null=True, + verbose_name="hidden subtasks", + ), + ), + ] diff --git a/judge/models/contest.py b/judge/models/contest.py index a225012..994e3ce 100644 --- a/judge/models/contest.py +++ b/judge/models/contest.py @@ -786,9 +786,9 @@ class ContestProblem(models.Model): MinValueValidator(0, _("Why include a problem you " "can't submit to?")) ], ) - frozen_subtasks = models.CharField( - help_text=_("Only for format new IOI. Separated by commas, e.g: 2, 3"), - verbose_name=_("frozen subtasks"), + hidden_subtasks = models.CharField( + help_text=_("Separated by commas, e.g: 2, 3"), + verbose_name=_("hidden subtasks"), null=True, blank=True, max_length=20, diff --git a/judge/views/contests.py b/judge/views/contests.py index 1f400bb..56580b9 100644 --- a/judge/views/contests.py +++ b/judge/views/contests.py @@ -295,7 +295,7 @@ class ContestMixin(object): context["meta_description"] = self.object.summary or metadata[0] context["og_image"] = self.object.og_image or metadata[1] context["has_moss_api_key"] = settings.MOSS_API_KEY is not None - context["can_use_resolver"] = self.object.format_name == "ioi16" + context["can_use_resolver"] = self.object.format.has_hidden_subtasks context["logo_override_image"] = self.object.logo_override_image if ( not context["logo_override_image"] @@ -989,7 +989,7 @@ def contest_ranking_ajax(request, contest, participation=None): raise Http404() if show_final: - if not request.user.is_superuser or contest.format_name != "ioi16": + if not request.user.is_superuser or not contest.format.has_hidden_subtasks: raise Http404() queryset = contest.users.filter(virtual__gte=0) diff --git a/judge/views/resolver.py b/judge/views/resolver.py index acb3fe9..2085194 100644 --- a/judge/views/resolver.py +++ b/judge/views/resolver.py @@ -18,7 +18,7 @@ class Resolver(TemplateView): for order, problem_id in problems: id_to_order[str(problem_id)] = order - frozen_subtasks = self.contest.format.get_frozen_subtasks() + hidden_subtasks = self.contest.format.get_hidden_subtasks() num_problems = len(problems) problem_sub = [0] * num_problems sub_frozen = [0] * num_problems @@ -122,10 +122,10 @@ class Resolver(TemplateView): self.contest.points_precision, ) - for i in frozen_subtasks: + for i in hidden_subtasks: order = id_to_order[i] - if frozen_subtasks[i]: - sub_frozen[order - 1] = min(frozen_subtasks[i]) + if hidden_subtasks[i]: + sub_frozen[order - 1] = min(hidden_subtasks[i]) else: sub_frozen[order - 1] = problem_sub[order - 1] + 1 return { @@ -143,6 +143,6 @@ class Resolver(TemplateView): def get(self, request, *args, **kwargs): if request.user.is_superuser: self.contest = Contest.objects.get(key=kwargs.get("contest")) - if self.contest.format_name == "ioi16": + if self.contest.format.has_hidden_subtasks: return super(Resolver, self).get(request, *args, **kwargs) return HttpResponseForbidden() diff --git a/judge/views/submission.py b/judge/views/submission.py index f18089f..e1de0f9 100644 --- a/judge/views/submission.py +++ b/judge/views/submission.py @@ -226,16 +226,18 @@ class SubmissionStatus(SubmissionDetailBase): return True return False - def get_frozen_subtasks(self): + def get_hidden_subtasks(self): if self.request.user.is_superuser: return set() submission = self.object contest = submission.contest_object - if contest and contest.format_name == "ioi16": - contest_problem = contest.contest_problems.get(problem=submission.problem) - return contest.format.get_frozen_subtasks().get( - str(contest_problem.id), set() - ) + if contest and contest.format.has_hidden_subtasks: + try: + return contest.format.get_hidden_subtasks().get( + str(submission.contest.problem.id), set() + ) + except Exception: + pass return set() def get_context_data(self, **kwargs): @@ -250,7 +252,7 @@ class SubmissionStatus(SubmissionDetailBase): context["highlighted_source"] = highlight_code( submission.source.source, submission.language.pygments, linenos=False ) - context["frozen_subtasks"] = self.get_frozen_subtasks() + context["hidden_subtasks"] = self.get_hidden_subtasks() contest = submission.contest_or_none prefix_length = 0 @@ -437,6 +439,13 @@ class SubmissionsListBase(DiggPaginatorMixin, TitleMixin, ListView): hidden_codes += ["IE"] return [(key, value) for key, value in all_statuses if key not in hidden_codes] + def should_show_result_data(self): + return not ( + self.in_contest + and self.contest.format.has_hidden_subtasks + and not self.request.user.is_superuser + ) + def get_context_data(self, **kwargs): context = super(SubmissionsListBase, self).get_context_data(**kwargs) authenticated = self.request.user.is_authenticated @@ -458,10 +467,13 @@ class SubmissionsListBase(DiggPaginatorMixin, TitleMixin, ListView): context["all_statuses"] = self.get_searchable_status_codes() context["selected_statuses"] = self.selected_statuses - context["results_json"] = mark_safe(json.dumps(self.get_result_data())) - context["results_colors_json"] = mark_safe( - json.dumps(settings.DMOJ_STATS_SUBMISSION_RESULT_COLORS) - ) + if self.should_show_result_data(): + context["results_json"] = mark_safe(json.dumps(self.get_result_data())) + context["results_colors_json"] = mark_safe( + json.dumps(settings.DMOJ_STATS_SUBMISSION_RESULT_COLORS) + ) + else: + context["results_json"] = None context["page_suffix"] = suffix = ( ("?" + self.request.GET.urlencode()) if self.request.GET else "" @@ -856,13 +868,13 @@ class UserContestSubmissionsAjax(UserContestSubmissions): return None def get_best_subtask_points(self): - if self.contest.format_name == "ioi16": + if self.contest.format.has_hidden_subtasks: contest_problem = self.contest.contest_problems.get(problem=self.problem) best_subtasks = {} total_points = 0 problem_points = 0 achieved_points = 0 - frozen_subtasks = self.contest.format.get_frozen_subtasks() + hidden_subtasks = self.contest.format.get_hidden_subtasks() for ( problem_id, @@ -882,7 +894,7 @@ class UserContestSubmissionsAjax(UserContestSubmissions): problem_points = pp submission = Submission.objects.get(id=sub_id) if ( - subtask in frozen_subtasks.get(str(problem_id), set()) + subtask in hidden_subtasks.get(str(problem_id), set()) and not self.request.user.is_superuser ): best_subtasks[subtask] = { @@ -930,7 +942,7 @@ class UserContestSubmissionsAjax(UserContestSubmissions): filtered_submissions = [] # Only show this for some users when using ioi16 - if self.contest.format_name != "ioi16" or self.request.user.is_superuser: + if self.contest.format.has_hidden_subtasks or self.request.user.is_superuser: for s in context["submissions"]: if not hasattr(s, "contest"): continue diff --git a/resources/base.scss b/resources/base.scss index 2234532..b2711e1 100644 --- a/resources/base.scss +++ b/resources/base.scss @@ -842,7 +842,7 @@ select { } .background-d6e8f7 { - background-color: d6e8f7; + background-color: #d6e8f7; } .background-bisque { diff --git a/resources/darkmode.css b/resources/darkmode.css index cb2c2d5..448a6f1 100644 --- a/resources/darkmode.css +++ b/resources/darkmode.css @@ -1786,6 +1786,9 @@ noscript #noscript { .blue { color: rgb(51, 125, 255); } +.background-d6e8f7 { + background-color: rgb(38, 41, 43); +} .background-bisque { background-color: rgb(86, 47, 0); } diff --git a/templates/problem/list.html b/templates/problem/list.html index cb4a5e0..fbdfbce 100644 --- a/templates/problem/list.html +++ b/templates/problem/list.html @@ -3,7 +3,7 @@ {% include "problem/left-sidebar.html" %} {% endblock %} -{% set in_ioi16 = request.in_contest_mode and request.participation.contest.format_name == "ioi16" %} +{% set has_hidden_subtasks = request.in_contest_mode and request.participation.contest.format.has_hidden_subtasks %} {% block middle_content %}
@@ -11,7 +11,7 @@ {% if request.in_contest_mode %} - {% if request.user.is_authenticated and not in_ioi16 %} + {% if request.user.is_authenticated and not has_hidden_subtasks %} {% endif %} {{ _('Problem') }} @@ -20,7 +20,7 @@ {{ _('Types') }} {% endif %} {{ _('Points') }} - {% if not in_ioi16 %} + {% if not has_hidden_subtasks %} {{ _('Users') }} {% endif %} {% else %} @@ -64,7 +64,7 @@ {% for problem in object_list %} - {% if request.user.is_authenticated and not in_ioi16 %} + {% if request.user.is_authenticated and not has_hidden_subtasks %} {% if problem.id in completed_problem_ids %} @@ -115,7 +115,7 @@ {% if not request.in_contest_mode %} {{ problem.ac_rate|floatformat(0) }}% {% endif %} - {% if not in_ioi16 %} + {% if not has_hidden_subtasks %} {% if not request.in_contest_mode or not hide_contest_scoreboard %} diff --git a/templates/submission/list.html b/templates/submission/list.html index 9e9c9d4..67caf04 100644 --- a/templates/submission/list.html +++ b/templates/submission/list.html @@ -23,7 +23,9 @@ window.show_problem = 0; {% endif %} {% endif %} - window.results_json = {{ results_json }}; + {% if results_json %} + window.results_json = {{ results_json }}; + {% endif %} {% compress js %} @@ -85,49 +87,51 @@ }); // Draw the statistics graph. - var chart = null; - function stats_graph(raw_data) { - var colors = {{ results_colors_json }}; + {% if results_json %} + var chart = null; + function stats_graph(raw_data) { + var colors = {{ results_colors_json }}; - var ctx = $('#status-graph').find('canvas')[0].getContext('2d'); - var font = $('body').css('font-family'); - if (chart !== null) { - chart.destroy(); + var ctx = $('#status-graph').find('canvas')[0].getContext('2d'); + var font = $('body').css('font-family'); + if (chart !== null) { + chart.destroy(); + } + chart = new Chart(ctx, { + type: 'pie', + data: { + datasets: [{ + data: raw_data.categories.map(function(entry) { + return entry.count; + }), + backgroundColor: raw_data.categories.map(function(entry) { + return colors[entry.code]; + }), + }], + labels: raw_data.categories.map(function(entry) { + return entry.name; + }), + }, + options: { + animation: false, + scaleFontFamily: font, + tooltips: { + titleFontFamily: font, + bodyFontFamily: font, + }, + legend: { + display: false, + }, + }, + }); + + $('#total-submission-count').text(raw_data.total); } - chart = new Chart(ctx, { - type: 'pie', - data: { - datasets: [{ - data: raw_data.categories.map(function(entry) { - return entry.count; - }), - backgroundColor: raw_data.categories.map(function(entry) { - return colors[entry.code]; - }), - }], - labels: raw_data.categories.map(function(entry) { - return entry.name; - }), - }, - options: { - animation: false, - scaleFontFamily: font, - tooltips: { - titleFontFamily: font, - bodyFontFamily: font, - }, - legend: { - display: false, - }, - }, + + $(function () { + stats_graph(window.results_json); }); - - $('#total-submission-count').text(raw_data.total); - } - - $(function () { - stats_graph(window.results_json); - }); + {% endif %} function load_dynamic_update(last_msg) { var _collect = function (e) { @@ -323,8 +327,7 @@ {% endblock %} {% block right_sidebar %} -{% set hide_sidebar = request.in_contest_mode and request.participation.contest.format_name == "ioi16" and not request.user.is_superuser %} -{% if not hide_sidebar %} +{% if results_json %}