diff --git a/oioioi/interactive/controllers.py b/oioioi/interactive/controllers.py index cf01aa72c..8a34152e6 100644 --- a/oioioi/interactive/controllers.py +++ b/oioioi/interactive/controllers.py @@ -1,7 +1,7 @@ from django.utils.translation import gettext_lazy as _ from oioioi.filetracker.utils import django_to_filetracker_path -from oioioi.interactive.models import Interactor +from oioioi.interactive.models import Interactor, InteractiveTaskInfo from oioioi.programs.controllers import ProgrammingProblemController @@ -13,6 +13,8 @@ def fill_evaluation_environ(self, environ, submission, **kwargs): interactor = Interactor.objects.get(problem=self.problem) environ['interactor_file'] = django_to_filetracker_path(interactor.exe_file) + info = InteractiveTaskInfo.objects.get(problem=self.problem) + environ['num_processes'] = info.num_processes environ['task_type_suffix'] = '-interactive-exec' diff --git a/oioioi/interactive/migrations/0002_interactivetaskinfo.py b/oioioi/interactive/migrations/0002_interactivetaskinfo.py new file mode 100644 index 000000000..6a10e145e --- /dev/null +++ b/oioioi/interactive/migrations/0002_interactivetaskinfo.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.13 on 2024-07-10 11:33 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('problems', '0031_auto_20220328_1124'), + ('interactive', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='InteractiveTaskInfo', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('num_processes', models.IntegerField(default=1, verbose_name="number of user's processes to run")), + ('problem', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='problems.problem')), + ], + ), + ] diff --git a/oioioi/interactive/models.py b/oioioi/interactive/models.py index 80abaf568..c1ba1a066 100644 --- a/oioioi/interactive/models.py +++ b/oioioi/interactive/models.py @@ -17,3 +17,10 @@ class Interactor(models.Model): class Meta(object): verbose_name = _("interactive executable file") verbose_name_plural = _("interactive executable files"), + + +class InteractiveTaskInfo(models.Model): + problem = models.OneToOneField(Problem, on_delete=models.CASCADE) + num_processes = models.IntegerField( + verbose_name=_("number of user's processes to run"), default=1 + ) diff --git a/oioioi/programs/handlers.py b/oioioi/programs/handlers.py index 03bcee9d2..96470db78 100755 --- a/oioioi/programs/handlers.py +++ b/oioioi/programs/handlers.py @@ -295,6 +295,8 @@ def run_tests(env, kind=None, **kwargs): job['upload_out'] = True if env.get('interactor_file'): job['interactor_file'] = env['interactor_file'] + if env.get('num_processes'): + job['num_processes'] = env['num_processes'] job['untrusted_checker'] = env['untrusted_checker'] jobs[test_name] = job extra_args = env.get('sioworkers_extra_args', {}).get(kind, {}) diff --git a/oioioi/sinolpack/controllers.py b/oioioi/sinolpack/controllers.py index c054a3ccb..f7fbf59c7 100644 --- a/oioioi/sinolpack/controllers.py +++ b/oioioi/sinolpack/controllers.py @@ -1,5 +1,6 @@ from django.utils.translation import gettext_lazy as _ +from oioioi.interactive.controllers import InteractiveProblemController from oioioi.programs.controllers import ProgrammingProblemController from oioioi.sinolpack.admin import SinolpackProblemAdminMixin from oioioi.sinolpack.utils import add_extra_files @@ -18,3 +19,18 @@ def mixins_for_admin(self): return super(SinolProblemController, self).mixins_for_admin() + ( SinolpackProblemAdminMixin, ) + + +class SinolInteractiveProblemController(InteractiveProblemController): + description = _("Sinol package interactive problem") + + def fill_evaluation_environ(self, environ, submission, **kwargs): + super(SinolInteractiveProblemController, self).fill_evaluation_environ( + environ, submission, **kwargs + ) + add_extra_files(environ, self.problem) + + def mixins_for_admin(self): + return super(SinolInteractiveProblemController, self).mixins_for_admin() + ( + SinolpackProblemAdminMixin, + ) diff --git a/oioioi/sinolpack/files/test_sigpipe_interactor.tgz b/oioioi/sinolpack/files/test_sigpipe_interactor.tgz index 604746d30..c1234375d 100644 Binary files a/oioioi/sinolpack/files/test_sigpipe_interactor.tgz and b/oioioi/sinolpack/files/test_sigpipe_interactor.tgz differ diff --git a/oioioi/sinolpack/files/test_simple_interactive.tgz b/oioioi/sinolpack/files/test_simple_interactive.tgz index c5ee37568..475e2d480 100644 Binary files a/oioioi/sinolpack/files/test_simple_interactive.tgz and b/oioioi/sinolpack/files/test_simple_interactive.tgz differ diff --git a/oioioi/sinolpack/package.py b/oioioi/sinolpack/package.py index 53f298460..08527acd1 100644 --- a/oioioi/sinolpack/package.py +++ b/oioioi/sinolpack/package.py @@ -28,7 +28,7 @@ filetracker_to_django_file, stream_file, ) -from oioioi.interactive.models import Interactor +from oioioi.interactive.models import Interactor, InteractiveTaskInfo from oioioi.problems.models import ( Problem, ProblemAttachment, @@ -394,7 +394,7 @@ def _get_controller_name(self): return self.controller_name return { TaskType.STANDARD: 'oioioi.sinolpack.controllers.SinolProblemController', - TaskType.INTERACTIVE: 'oioioi.interactive.controllers.InteractiveProblemController', + TaskType.INTERACTIVE: 'oioioi.sinolpack.controllers.SinolInteractiveProblemController', }[self.task_type] def _extract_and_process_package(self): @@ -469,6 +469,16 @@ def _process_config_yml(self): instance.config = '' instance.save() self.config = instance.parsed_config + if self.task_type == TaskType.INTERACTIVE: + self._process_interactive_config() + + @_describe_processing_error + def _process_interactive_config(self): + instance, _ = InteractiveTaskInfo.objects.get_or_create(problem=self.problem) + if 'num_processes' in self.config: + instance.num_processes = self.config['num_processes'] + instance.save() + @_describe_processing_error def _detect_task_type(self): @@ -784,7 +794,7 @@ def _create_instances_for_tests(self): outs_to_make = [] scored_groups = set() - if self.use_make and not self.config.get('no_outgen', False): + if self.task_type != TaskType.INTERACTIVE and self.use_make and not self.config.get('no_outgen', False): self._find_and_compile('', command='outgen') for order, test in enumerate(sorted(all_items, key=naturalsort_key)): diff --git a/oioioi/sinolpack/tests.py b/oioioi/sinolpack/tests.py index 2088bc45c..00b09d227 100644 --- a/oioioi/sinolpack/tests.py +++ b/oioioi/sinolpack/tests.py @@ -695,8 +695,7 @@ def _check_sigpipe_interactor_package(self, problem): for test in tests: test_report = TestReport.objects.get(test=test, submission_report__submission=s1) self.assertEqual(test_report.status, 'WA') - # HACK: Temporary Fix, just to silent this broken test, to be repaired later - self.assertIn(test_report.comment, ['', 'solution exited prematurely']) + self.assertIn(test_report.comment, 'solution exited prematurely') s2 = ModelProgramSubmission.objects.get(model_solution=sol_re) for test in tests: diff --git a/requirements.txt b/requirements.txt index 80b42f931..3c8bbc9e9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # These dependencies need to be installed from external sources, # therefore they must be listed here. Moreover, they cannot be listed in # setup.py, as pip is not able to install them. -http://github.com/sio2project/sioworkers/archive/refs/tags/v1.5.3.tar.gz +http://github.com/sio2project/sioworkers/archive/refs/tags/v1.5.5.tar.gz -e .