-
Notifications
You must be signed in to change notification settings - Fork 8
feat(checker): Add codeforces-batch-v1 judge #677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| # pisek - Tool for developing tasks for programming competitions. | ||
| # | ||
| # Copyright (c) 2026 Daniel Skýpala <skipy@kam.mff.cuni.cz> | ||
|
|
||
| # This program is free software: you can redistribute it and/or modify | ||
| # it under the terms of the GNU General Public License as published by | ||
| # the Free Software Foundation, either version 3 of the License, or | ||
| # any later version. | ||
| # | ||
| # You should have received a copy of the GNU General Public License | ||
| # along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
|
||
| from decimal import Decimal | ||
|
|
||
| from pisek.utils.paths import IInputPath, IOutputPath | ||
| from pisek.env.env import Env | ||
| from pisek.config.config_types import ProgramRole | ||
| from pisek.config.task_config import RunSection | ||
| from pisek.task_jobs.solution.solution_result import ( | ||
| Verdict, | ||
| SolutionResult, | ||
| RelativeSolutionResult, | ||
| ) | ||
|
|
||
| from pisek.task_jobs.checker.checker_base import RunBatchChecker | ||
|
|
||
|
|
||
| class RunCodeforcesBatchV1Judge(RunBatchChecker): | ||
| """Checks solution output using judge with the codeforces interface. (Abstract class)""" | ||
|
|
||
| def __init__( | ||
| self, | ||
| env: Env, | ||
| judge: RunSection, | ||
| test: int, | ||
| input_: IInputPath, | ||
| output: IOutputPath, | ||
| correct_output: IOutputPath, | ||
| expected_verdict: Verdict | None, | ||
| **kwargs, | ||
| ) -> None: | ||
| super().__init__( | ||
| env=env, | ||
| checker_name=judge.name, | ||
| test=test, | ||
| input_=input_, | ||
| output=output, | ||
| correct_output=correct_output, | ||
| expected_verdict=expected_verdict, | ||
| **kwargs, | ||
| ) | ||
| self.judge = judge | ||
|
|
||
| def _check(self) -> SolutionResult: | ||
| config = self._env.config | ||
| report = self.checker_log_file.replace_suffix(".report") | ||
|
|
||
| self._access_file(self.output) | ||
| self._access_file(report) | ||
| if config.judge_needs_in: | ||
| self._access_file(self.input) | ||
| if config.judge_needs_out: | ||
| self._access_file(self.correct_output) | ||
|
|
||
| self.checker_rr = self._run_program( | ||
| ProgramRole.judge, | ||
| self.judge, | ||
| args=[ | ||
| self._maybe_input_path(), | ||
| self.output.abspath, | ||
| self._maybe_correct_output_path(), | ||
| report.abspath, | ||
| ], | ||
| stderr=self.checker_log_file, | ||
| ) | ||
|
|
||
| if self.checker_rr.returncode == 0: | ||
| return RelativeSolutionResult( | ||
| verdict=Verdict.ok, | ||
| message="OK", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't the message be the content of the report file?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I always treated the message as the thing shown to participants. Also report file can be multiline.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The checker comment is shown to participants, just only on samples during the contest proper.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And message is always shown to the participants in the opendata module.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not a perfect match, but I feel it's kind of like when CMS only shows you the verdict for some test cases. Regardless of if the comment is the same thing as a message, we should record it and show it in verbose mode. (And, in the future, make it available in the opendata module.)
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, that is why this is a draft PR. |
||
| relative_points=Decimal(1), | ||
| ) | ||
| elif self.checker_rr.returncode == 1: | ||
| return RelativeSolutionResult( | ||
| verdict=Verdict.wrong_answer, | ||
| message="Wrong answer", | ||
| relative_points=Decimal(0), | ||
| ) | ||
| elif self.checker_rr.returncode == 2: | ||
| return RelativeSolutionResult( | ||
| verdict=Verdict.wrong_answer, | ||
| message="Presentation error", | ||
| relative_points=Decimal(0), | ||
| ) | ||
| else: | ||
| raise self._create_program_failure( | ||
| f"Judge failed on output {self.output:n}:", | ||
| self.checker_rr, | ||
| stderr_force_content=True, | ||
| ) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
testlib.hwill always open all files. While it does not seem to be a problem if a file does not exists, if it does exist, at least its size will be checked. An attacker could create a large file or directory with the right name in/tmp/to cause the judge to crash.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you would pass all the files always?