Skip to content

Commit b82ae56

Browse files
authored
Set oicompare language to user's language (#403)
* Set oicompare language to user's language * Remove debug * Fix bug * Allow changing oicompare format * Change test for oicompare
1 parent 9d763fb commit b82ae56

File tree

10 files changed

+189
-4
lines changed

10 files changed

+189
-4
lines changed

oioioi/contestexcl/tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ def _modify_contestexcl(
189189
('contestlogo', 0, 0, 0, 1),
190190
('programs_config', 0, 0, 0, 1),
191191
('contestcompiler_set', 0, 0, 0, 1000),
192+
('checkerformatforcontest', 0, 0, 0, 1),
192193
)
193194
data = dict()
194195
for (name, total, initial, min_num, max_num) in formsets:

oioioi/problems/controllers.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from oioioi.evalmgr.tasks import create_environ, delay_environ
2525
from oioioi.problems.models import ProblemStatistics, UserStatistics
2626
from oioioi.problems.utils import can_admin_problem
27+
from oioioi.programs.utils import get_checker_format
2728

2829
logger = logging.getLogger(__name__)
2930

@@ -148,6 +149,17 @@ def judge(self, submission, extra_args=None, is_rejudge=False):
148149
environ = create_environ()
149150
environ['extra_args'] = extra_args or {}
150151
environ['is_rejudge'] = is_rejudge
152+
if hasattr(submission, 'programsubmission'):
153+
user_lang = None
154+
for code, lang in settings.LANGUAGES:
155+
if code == submission.programsubmission.user_language_code:
156+
user_lang = lang.lower()
157+
break
158+
if user_lang:
159+
environ['user_language'] = user_lang
160+
else:
161+
environ['user_language'] = 'english'
162+
environ['checker_format'] = environ['user_language'] + '_' + get_checker_format(submission.problem_instance)
151163
picontroller = submission.problem_instance.controller
152164

153165
picontroller.fill_evaluation_environ(environ, submission)

oioioi/programs/admin.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
ProgramsConfig,
3232
ReportActionsConfig,
3333
Test,
34+
CheckerFormatForContest,
35+
CheckerFormatForProblem,
3436
)
3537

3638

@@ -447,3 +449,38 @@ def queryset(self, request, queryset):
447449
return queryset.filter(condition)
448450
else:
449451
return queryset
452+
453+
454+
class CheckerFormatForContestInline(admin.StackedInline):
455+
model = CheckerFormatForContest
456+
category = _("Advanced")
457+
458+
459+
class CheckerFormatForProblemInline(admin.StackedInline):
460+
model = CheckerFormatForProblem
461+
category = _("Advanced")
462+
463+
464+
class CheckerFormatOverrideContestAdminMixin(object):
465+
"""Adds :class:`~oioioi.programs.models.CheckerFormatForContest` to an admin
466+
panel.
467+
"""
468+
def __init__(self, *args, **kwargs):
469+
super(CheckerFormatOverrideContestAdminMixin, self).__init__(*args, **kwargs)
470+
self.inlines = tuple(self.inlines) + (CheckerFormatForContestInline,)
471+
472+
473+
ContestAdmin.mix_in(CheckerFormatOverrideContestAdminMixin)
474+
475+
476+
class CheckerFormatOverrideProblemAdminMixin(object):
477+
"""Adds :class:`~oioioi.programs.models.CheckerFormatForProblem` to an admin
478+
panel.
479+
"""
480+
481+
def __init__(self, *args, **kwargs):
482+
super(CheckerFormatOverrideProblemAdminMixin, self).__init__(*args, **kwargs)
483+
self.inlines = tuple(self.inlines) + (CheckerFormatForProblemInline,)
484+
485+
486+
ProblemInstanceAdmin.mix_in(CheckerFormatOverrideProblemAdminMixin)

oioioi/programs/controllers.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from django.template.loader import render_to_string
1212
from django.urls import reverse
1313
from django.utils.safestring import mark_safe
14-
from django.utils.translation import gettext_lazy as _
14+
from django.utils.translation import gettext_lazy as _, get_language_from_request
1515

1616
from oioioi.base.preferences import ensure_preferences_exist_for_user
1717
from oioioi.base.utils.inputs import narrow_input_field
@@ -529,6 +529,7 @@ def create_submission(
529529
),
530530
),
531531
date=request.timestamp,
532+
user_language_code=get_language_from_request(request),
532533
)
533534

534535
file = form_data['file']

oioioi/programs/handlers.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ def run_tests(env, kind=None, **kwargs):
289289
job['check_output'] = env.get('check_outputs', True)
290290
if env.get('checker'):
291291
job['chk_file'] = env['checker']
292+
job['checker_format'] = env.get('checker_format', 'english_abbreviated')
292293
if env.get('save_outputs'):
293294
job.setdefault('out_file', _make_filename(env, test_name + '.out'))
294295
job['upload_out'] = True
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Generated by Django 4.2.16 on 2024-09-15 21:27
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
import oioioi.base.fields
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('contests', '0018_contest_show_contest_rules'),
12+
('programs', '0019_add_limits_override'),
13+
]
14+
15+
operations = [
16+
migrations.AddField(
17+
model_name='programsubmission',
18+
name='user_language_code',
19+
field=models.CharField(blank=True, max_length=6, null=True, verbose_name='User language code'),
20+
),
21+
migrations.CreateModel(
22+
name='CheckerFormatForProblem',
23+
fields=[
24+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
25+
('format', oioioi.base.fields.EnumField(max_length=64, verbose_name='format')),
26+
('problem_instance', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='contests.probleminstance', verbose_name='problem instance')),
27+
],
28+
options={
29+
'verbose_name': 'checker format for problem',
30+
'verbose_name_plural': 'checker formats for problems',
31+
'ordering': ('problem_instance',),
32+
'unique_together': {('problem_instance', 'format')},
33+
},
34+
),
35+
migrations.CreateModel(
36+
name='CheckerFormatForContest',
37+
fields=[
38+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
39+
('format', oioioi.base.fields.EnumField(help_text="Format of the checker output for this contest. Abbreviated describes the output difference, while Terse doesn't give any details.", max_length=64, verbose_name='format')),
40+
('contest', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='contests.contest', verbose_name='contest')),
41+
],
42+
options={
43+
'verbose_name': 'checker format for contest',
44+
'verbose_name_plural': 'checker formats for contests',
45+
'ordering': ('contest',),
46+
'unique_together': {('contest', 'format')},
47+
},
48+
),
49+
]

oioioi/programs/models.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ class ProgramSubmission(Submission):
261261
source_length = models.IntegerField(
262262
verbose_name=_("Source code length"), blank=True, null=True
263263
)
264+
# Stores the language used by the user in the moment of submitting the solution
265+
user_language_code = models.CharField(max_length=6, verbose_name=_("User language code"), blank=True, null=True)
264266

265267
def save(self, *args, **kwargs):
266268
if self.source_file:
@@ -461,3 +463,44 @@ def check_compilers_config():
461463

462464

463465
check_compilers_config()
466+
467+
468+
CheckerFormat = EnumRegistry()
469+
CheckerFormat.register('terse', _("Terse"))
470+
CheckerFormat.register('abbreviated', _("Abbreviated"))
471+
472+
473+
class CheckerFormatForContest(models.Model):
474+
"""Overrides the default checker's format (abbreviated) for a contest."""
475+
476+
contest = models.OneToOneField(
477+
Contest, verbose_name=_("contest"), on_delete=models.CASCADE
478+
)
479+
format = EnumField(
480+
CheckerFormat,
481+
verbose_name=_("format"),
482+
help_text=_("Format of the checker output for this contest. "
483+
"Abbreviated describes the output difference, while "
484+
"Terse doesn't give any details.")
485+
)
486+
487+
class Meta(object):
488+
verbose_name = _("checker format for contest")
489+
verbose_name_plural = _("checker formats for contests")
490+
ordering = ('contest',)
491+
unique_together = ('contest', 'format')
492+
493+
494+
class CheckerFormatForProblem(models.Model):
495+
"""Overrides the default checker's format (abbreviated) for a problem."""
496+
497+
problem_instance = models.OneToOneField(
498+
ProblemInstance, verbose_name=_("problem instance"), on_delete=models.CASCADE
499+
)
500+
format = EnumField(CheckerFormat, verbose_name=_("format"))
501+
502+
class Meta(object):
503+
verbose_name = _("checker format for problem")
504+
verbose_name_plural = _("checker formats for problems")
505+
ordering = ('problem_instance',)
506+
unique_together = ('problem_instance', 'format')

oioioi/programs/tests.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@
4646
LanguageOverrideForTest,
4747
TestReport,
4848
check_compilers_config,
49+
CheckerFormatForContest,
50+
CheckerFormatForProblem,
4951
)
5052
from oioioi.programs.problem_instance_utils import get_allowed_languages_dict
51-
from oioioi.programs.utils import form_field_id_for_langs
53+
from oioioi.programs.utils import form_field_id_for_langs, get_checker_format
5254
from oioioi.programs.views import _testreports_to_generate_outs
5355
from oioioi.sinolpack.models import ExtraConfig
5456
from oioioi.sinolpack.tests import get_test_filename
@@ -544,7 +546,7 @@ def fake_send_notification(
544546
NotificationHandler.send_notification = fake_send_notification
545547

546548
submission = Submission.objects.get(pk=1)
547-
549+
548550
environ = create_environ()
549551
environ['extra_args'] = {}
550552
environ['is_rejudge'] = False
@@ -1986,3 +1988,27 @@ def test_proper_env_override(self):
19861988
self.assertEqual(
19871989
env_with_tests['tests']['1a']['exec_mem_limit'], tests[1].memory_limit
19881990
)
1991+
1992+
1993+
class TestOICompare(TestCase):
1994+
fixtures = ['test_contest', 'test_problem_instance', 'test_full_package']
1995+
1996+
def test_format(self):
1997+
contest = Contest.objects.get()
1998+
pi = ProblemInstance.objects.get()
1999+
for format_contest, format_problem, expected in [
2000+
(None, None, 'abbreviated'),
2001+
('terse', None, 'terse'),
2002+
('terse', 'abbreviated', 'abbreviated'),
2003+
(None, 'terse', 'terse'),
2004+
]:
2005+
CheckerFormatForContest.objects.all().delete()
2006+
CheckerFormatForProblem.objects.all().delete()
2007+
if format_problem is not None:
2008+
CheckerFormatForProblem.objects.create(
2009+
problem_instance=pi, format=format_problem
2010+
)
2011+
if format_contest is not None:
2012+
CheckerFormatForContest.objects.create(contest=contest, format=format_contest)
2013+
2014+
self.assertEqual(get_checker_format(pi), expected)

oioioi/programs/utils.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
ModelProgramSubmission,
1818
ProgramSubmission,
1919
ReportActionsConfig,
20+
CheckerFormatForContest,
21+
CheckerFormatForProblem,
2022
)
2123

2224

@@ -215,3 +217,16 @@ def get_submittable_languages():
215217
for _, lang_config in submittable_languages.items():
216218
lang_config.setdefault('type', 'main')
217219
return submittable_languages
220+
221+
222+
def get_checker_format(problem_instance):
223+
try:
224+
return CheckerFormatForProblem.objects.get(problem_instance=problem_instance).format
225+
except CheckerFormatForProblem.DoesNotExist:
226+
if problem_instance.contest:
227+
try:
228+
return CheckerFormatForContest.objects.get(contest=problem_instance.contest).format
229+
except CheckerFormatForContest.DoesNotExist:
230+
return getattr(settings, 'DEFAULT_CHECKER_FORMAT', 'abbreviated')
231+
else:
232+
return getattr(settings, 'DEFAULT_CHECKER_FORMAT', 'abbreviated')

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# These dependencies need to be installed from external sources,
22
# therefore they must be listed here. Moreover, they cannot be listed in
33
# setup.py, as pip is not able to install them.
4-
http://github.com/sio2project/sioworkers/archive/refs/tags/v1.5.2.tar.gz
4+
http://github.com/sio2project/sioworkers/archive/refs/tags/v1.5.3.tar.gz
55

66
-e .

0 commit comments

Comments
 (0)