rbx.cp 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rbx/__init__.py +0 -0
- rbx/annotations.py +127 -0
- rbx/autoenum.py +333 -0
- rbx/box/__init__.py +0 -0
- rbx/box/builder.py +77 -0
- rbx/box/cd.py +37 -0
- rbx/box/checkers.py +134 -0
- rbx/box/code.py +185 -0
- rbx/box/compile.py +56 -0
- rbx/box/conftest.py +42 -0
- rbx/box/contest/__init__.py +0 -0
- rbx/box/contest/build_contest_statements.py +347 -0
- rbx/box/contest/contest_package.py +76 -0
- rbx/box/contest/contest_utils.py +20 -0
- rbx/box/contest/main.py +179 -0
- rbx/box/contest/schema.py +155 -0
- rbx/box/contest/statements.py +82 -0
- rbx/box/creation.py +72 -0
- rbx/box/download.py +64 -0
- rbx/box/environment.py +345 -0
- rbx/box/extensions.py +26 -0
- rbx/box/generators.py +478 -0
- rbx/box/generators_test.py +63 -0
- rbx/box/main.py +449 -0
- rbx/box/package.py +316 -0
- rbx/box/packaging/boca/extension.py +27 -0
- rbx/box/packaging/boca/packager.py +245 -0
- rbx/box/packaging/contest_main.py +82 -0
- rbx/box/packaging/main.py +68 -0
- rbx/box/packaging/packager.py +117 -0
- rbx/box/packaging/polygon/packager.py +320 -0
- rbx/box/packaging/polygon/test.py +81 -0
- rbx/box/packaging/polygon/xml_schema.py +106 -0
- rbx/box/presets/__init__.py +503 -0
- rbx/box/presets/fetch.py +70 -0
- rbx/box/presets/lock_schema.py +20 -0
- rbx/box/presets/schema.py +59 -0
- rbx/box/schema.py +394 -0
- rbx/box/solutions.py +792 -0
- rbx/box/solutions_test.py +41 -0
- rbx/box/statements/__init__.py +0 -0
- rbx/box/statements/build_statements.py +359 -0
- rbx/box/statements/builders.py +375 -0
- rbx/box/statements/joiners.py +113 -0
- rbx/box/statements/latex.py +47 -0
- rbx/box/statements/latex_jinja.py +214 -0
- rbx/box/statements/schema.py +138 -0
- rbx/box/stresses.py +292 -0
- rbx/box/stressing/__init__.py +0 -0
- rbx/box/stressing/finder_parser.py +359 -0
- rbx/box/stressing/generator_parser.py +258 -0
- rbx/box/testcases.py +54 -0
- rbx/box/ui/__init__.py +0 -0
- rbx/box/ui/captured_log.py +372 -0
- rbx/box/ui/css/app.tcss +48 -0
- rbx/box/ui/main.py +38 -0
- rbx/box/ui/run.py +209 -0
- rbx/box/validators.py +245 -0
- rbx/box/validators_test.py +15 -0
- rbx/checker.py +128 -0
- rbx/clone.py +197 -0
- rbx/config.py +271 -0
- rbx/conftest.py +38 -0
- rbx/console.py +27 -0
- rbx/create.py +37 -0
- rbx/edit.py +24 -0
- rbx/grading/__init__.py +0 -0
- rbx/grading/caching.py +356 -0
- rbx/grading/conftest.py +33 -0
- rbx/grading/judge/__init__.py +0 -0
- rbx/grading/judge/cacher.py +503 -0
- rbx/grading/judge/digester.py +35 -0
- rbx/grading/judge/sandbox.py +748 -0
- rbx/grading/judge/sandboxes/__init__.py +0 -0
- rbx/grading/judge/sandboxes/isolate.py +683 -0
- rbx/grading/judge/sandboxes/stupid_sandbox.py +310 -0
- rbx/grading/judge/sandboxes/timeit.py +217 -0
- rbx/grading/judge/storage.py +284 -0
- rbx/grading/judge/test.py +38 -0
- rbx/grading/judge/testiso.py +54 -0
- rbx/grading/steps.py +522 -0
- rbx/grading/steps_with_caching.py +59 -0
- rbx/grading/steps_with_caching_run_test.py +429 -0
- rbx/grading_utils.py +148 -0
- rbx/hydration.py +101 -0
- rbx/main.py +122 -0
- rbx/metadata.py +105 -0
- rbx/providers/__init__.py +43 -0
- rbx/providers/codeforces.py +73 -0
- rbx/providers/provider.py +26 -0
- rbx/resources/checkers/boilerplate.cpp +20 -0
- rbx/resources/default_config.json +48 -0
- rbx/resources/envs/default.rbx.yml +37 -0
- rbx/resources/envs/isolate.rbx.yml +37 -0
- rbx/resources/packagers/boca/checker.sh +43 -0
- rbx/resources/packagers/boca/compare +53 -0
- rbx/resources/packagers/boca/compile/c +172 -0
- rbx/resources/packagers/boca/compile/cc +173 -0
- rbx/resources/packagers/boca/compile/cpp +172 -0
- rbx/resources/packagers/boca/compile/java +194 -0
- rbx/resources/packagers/boca/compile/kt +155 -0
- rbx/resources/packagers/boca/compile/pas +172 -0
- rbx/resources/packagers/boca/compile/py2 +173 -0
- rbx/resources/packagers/boca/compile/py3 +173 -0
- rbx/resources/packagers/boca/run/c +128 -0
- rbx/resources/packagers/boca/run/cc +128 -0
- rbx/resources/packagers/boca/run/cpp +128 -0
- rbx/resources/packagers/boca/run/java +194 -0
- rbx/resources/packagers/boca/run/kt +159 -0
- rbx/resources/packagers/boca/run/py2 +166 -0
- rbx/resources/packagers/boca/run/py3 +166 -0
- rbx/resources/presets/default/contest/contest.rbx.yml +14 -0
- rbx/resources/presets/default/contest/statement/contest.rbx.tex +97 -0
- rbx/resources/presets/default/contest/statement/olymp.sty +250 -0
- rbx/resources/presets/default/contest/statement/template.rbx.tex +42 -0
- rbx/resources/presets/default/preset.rbx.yml +12 -0
- rbx/resources/presets/default/problem/.gitignore +6 -0
- rbx/resources/presets/default/problem/gen.cpp +9 -0
- rbx/resources/presets/default/problem/problem.rbx.yml +44 -0
- rbx/resources/presets/default/problem/random.py +3 -0
- rbx/resources/presets/default/problem/random.txt +2 -0
- rbx/resources/presets/default/problem/sols/main.cpp +9 -0
- rbx/resources/presets/default/problem/sols/slow.cpp +15 -0
- rbx/resources/presets/default/problem/sols/wa.cpp +9 -0
- rbx/resources/presets/default/problem/statement/olymp.sty +250 -0
- rbx/resources/presets/default/problem/statement/projecao.png +0 -0
- rbx/resources/presets/default/problem/statement/statement.rbx.tex +18 -0
- rbx/resources/presets/default/problem/statement/template.rbx.tex +89 -0
- rbx/resources/presets/default/problem/tests/samples/000.in +1 -0
- rbx/resources/presets/default/problem/tests/samples/001.in +1 -0
- rbx/resources/presets/default/problem/validator.cpp +16 -0
- rbx/resources/presets/default/problem/wcmp.cpp +34 -0
- rbx/resources/templates/template.cpp +19 -0
- rbx/run.py +45 -0
- rbx/schema.py +64 -0
- rbx/submit.py +61 -0
- rbx/submitors/__init__.py +18 -0
- rbx/submitors/codeforces.py +120 -0
- rbx/submitors/submitor.py +25 -0
- rbx/test.py +347 -0
- rbx/testcase.py +70 -0
- rbx/testcase_rendering.py +79 -0
- rbx/testdata/box1/gen1.cpp +7 -0
- rbx/testdata/box1/gen2.cpp +9 -0
- rbx/testdata/box1/genScript.py +2 -0
- rbx/testdata/box1/hard-tle.sol.cpp +26 -0
- rbx/testdata/box1/ole.cpp +17 -0
- rbx/testdata/box1/problem.rbx.yml +39 -0
- rbx/testdata/box1/re.sol.cpp +23 -0
- rbx/testdata/box1/sol.cpp +22 -0
- rbx/testdata/box1/tests/1.in +1 -0
- rbx/testdata/box1/tle-and-incorrect.sol.cpp +33 -0
- rbx/testdata/box1/tle.sol.cpp +35 -0
- rbx/testdata/box1/validator.cpp +11 -0
- rbx/testdata/box1/wa.sol.cpp +22 -0
- rbx/testdata/caching/executable.py +1 -0
- rbx/testdata/compatible +0 -0
- rbx/testing_utils.py +65 -0
- rbx/utils.py +162 -0
- rbx_cp-0.5.0.dist-info/LICENSE +201 -0
- rbx_cp-0.5.0.dist-info/METADATA +89 -0
- rbx_cp-0.5.0.dist-info/RECORD +164 -0
- rbx_cp-0.5.0.dist-info/WHEEL +4 -0
- rbx_cp-0.5.0.dist-info/entry_points.txt +4 -0
rbx/main.py
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# flake8: noqa
|
2
|
+
from gevent import monkey
|
3
|
+
|
4
|
+
monkey.patch_all()
|
5
|
+
|
6
|
+
import typer
|
7
|
+
from typing_extensions import Annotated
|
8
|
+
|
9
|
+
from rbx import annotations, checker, config, testcase
|
10
|
+
from rbx import clone as clone_pkg
|
11
|
+
from rbx import create as create_pkg
|
12
|
+
from rbx import edit as edit_pkg
|
13
|
+
from rbx import run as run_pkg
|
14
|
+
from rbx import submit as submit_pkg
|
15
|
+
from rbx import test as test_pkg
|
16
|
+
from rbx.box import main
|
17
|
+
|
18
|
+
app = typer.Typer(no_args_is_help=True, cls=annotations.AliasGroup)
|
19
|
+
app.add_typer(main.app, name='box', cls=annotations.AliasGroup)
|
20
|
+
app.add_typer(
|
21
|
+
config.app,
|
22
|
+
name='config, cfg',
|
23
|
+
cls=annotations.AliasGroup,
|
24
|
+
help='Manage the configuration of the tool.',
|
25
|
+
)
|
26
|
+
app.add_typer(
|
27
|
+
testcase.app,
|
28
|
+
name='testcase, tc',
|
29
|
+
cls=annotations.AliasGroup,
|
30
|
+
help='Commands to manage the testcases of a problem.',
|
31
|
+
)
|
32
|
+
app.add_typer(
|
33
|
+
checker.app,
|
34
|
+
name='checker, check',
|
35
|
+
cls=annotations.AliasGroup,
|
36
|
+
help='Commands to manage the checker of a problem.',
|
37
|
+
)
|
38
|
+
|
39
|
+
|
40
|
+
@app.command('clone, c')
|
41
|
+
def clone(lang: annotations.Language):
|
42
|
+
"""
|
43
|
+
Clones by waiting for a set of problems to be sent through Competitive Companion.
|
44
|
+
"""
|
45
|
+
clone_pkg.main(lang=lang)
|
46
|
+
|
47
|
+
|
48
|
+
@app.command('new, n')
|
49
|
+
def new(
|
50
|
+
name: str,
|
51
|
+
language: annotations.Language,
|
52
|
+
timelimit: annotations.Timelimit = 1000,
|
53
|
+
memorylimit: annotations.Memorylimit = 256,
|
54
|
+
multitest: annotations.Multitest = False,
|
55
|
+
):
|
56
|
+
"""
|
57
|
+
Create a new problem from scratch.
|
58
|
+
"""
|
59
|
+
create_pkg.main(name, language, timelimit, memorylimit, multitest)
|
60
|
+
|
61
|
+
|
62
|
+
@app.command('edit, e')
|
63
|
+
def edit(
|
64
|
+
problem: annotations.Problem, language: annotations.LanguageWithDefault = None
|
65
|
+
):
|
66
|
+
"""
|
67
|
+
Edit the code of a problem using the provided language.
|
68
|
+
"""
|
69
|
+
edit_pkg.main(problem, language)
|
70
|
+
|
71
|
+
|
72
|
+
@app.command('test, t')
|
73
|
+
def test(
|
74
|
+
problem: annotations.Problem,
|
75
|
+
language: annotations.LanguageWithDefault = None,
|
76
|
+
keep_sandbox: bool = False,
|
77
|
+
index: annotations.TestcaseIndex = None,
|
78
|
+
interactive: Annotated[bool, typer.Option('--interactive', '--int')] = False,
|
79
|
+
):
|
80
|
+
"""
|
81
|
+
Test a problem using the provided language.
|
82
|
+
"""
|
83
|
+
test_pkg.main(
|
84
|
+
problem,
|
85
|
+
language,
|
86
|
+
keep_sandbox=keep_sandbox,
|
87
|
+
index=index,
|
88
|
+
interactive=interactive,
|
89
|
+
)
|
90
|
+
|
91
|
+
|
92
|
+
@app.command('run, r')
|
93
|
+
def run(
|
94
|
+
problem: annotations.Problem,
|
95
|
+
language: annotations.LanguageWithDefault = None,
|
96
|
+
keep_sandbox: bool = False,
|
97
|
+
):
|
98
|
+
"""
|
99
|
+
Run a problem using the provided language.
|
100
|
+
"""
|
101
|
+
run_pkg.main(
|
102
|
+
problem,
|
103
|
+
language,
|
104
|
+
keep_sandbox=keep_sandbox,
|
105
|
+
)
|
106
|
+
|
107
|
+
|
108
|
+
@app.command('submit, s')
|
109
|
+
def submit(
|
110
|
+
problem: annotations.Problem,
|
111
|
+
language: annotations.LanguageWithDefault = None,
|
112
|
+
keep_sandbox: bool = False,
|
113
|
+
):
|
114
|
+
"""
|
115
|
+
Submit a problem using the provided language.
|
116
|
+
"""
|
117
|
+
submit_pkg.main(problem, language, keep_sandbox=keep_sandbox)
|
118
|
+
|
119
|
+
|
120
|
+
@app.callback()
|
121
|
+
def callback():
|
122
|
+
pass
|
rbx/metadata.py
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
import pathlib
|
2
|
+
from typing import List, Optional, Tuple
|
3
|
+
|
4
|
+
from rbx.schema import DumpedProblem
|
5
|
+
|
6
|
+
|
7
|
+
def _normalize_alias(alias: str) -> str:
|
8
|
+
return alias.lower()
|
9
|
+
|
10
|
+
|
11
|
+
def _find_alias(alias: str, haystack: List[str]) -> Optional[int]:
|
12
|
+
normalized_alias = _normalize_alias(alias)
|
13
|
+
for i, candidate in enumerate(haystack):
|
14
|
+
if _normalize_alias(candidate) == normalized_alias:
|
15
|
+
return i
|
16
|
+
return None
|
17
|
+
|
18
|
+
|
19
|
+
def _get_best_alias_from_candidates(
|
20
|
+
alias: str, candidates: List[Tuple[pathlib.Path, DumpedProblem]]
|
21
|
+
) -> Optional[Tuple[pathlib.Path, DumpedProblem]]:
|
22
|
+
best_priority = 1e9
|
23
|
+
best_candidates = []
|
24
|
+
for path, problem in candidates:
|
25
|
+
index = _find_alias(alias, problem.aliases)
|
26
|
+
if index is None:
|
27
|
+
continue
|
28
|
+
if index < best_priority:
|
29
|
+
best_priority = index
|
30
|
+
best_candidates = [(path, problem)]
|
31
|
+
elif index == best_priority:
|
32
|
+
best_candidates.append((path, problem))
|
33
|
+
|
34
|
+
if len(best_candidates) != 1:
|
35
|
+
# TODO
|
36
|
+
return None
|
37
|
+
|
38
|
+
return best_candidates[0]
|
39
|
+
|
40
|
+
|
41
|
+
def find_problem_path_by_code(
|
42
|
+
code: str, root: Optional[pathlib.Path] = None
|
43
|
+
) -> Optional[pathlib.Path]:
|
44
|
+
if not root:
|
45
|
+
root = pathlib.Path()
|
46
|
+
|
47
|
+
metadata_path = root / f'{code}.rbx.json'
|
48
|
+
if not metadata_path.is_file():
|
49
|
+
return None
|
50
|
+
return metadata_path
|
51
|
+
|
52
|
+
|
53
|
+
def find_problem_path_by_alias(
|
54
|
+
alias: str, root: Optional[pathlib.Path] = None
|
55
|
+
) -> Optional[pathlib.Path]:
|
56
|
+
if not root:
|
57
|
+
root = pathlib.Path()
|
58
|
+
|
59
|
+
candidates: List[Tuple[pathlib.Path, DumpedProblem]] = []
|
60
|
+
for metadata_path in root.glob('*.rbx.json'):
|
61
|
+
problem = DumpedProblem.model_validate_json(metadata_path.read_text())
|
62
|
+
if _find_alias(alias, problem.aliases) is not None:
|
63
|
+
candidates.append((metadata_path, problem))
|
64
|
+
|
65
|
+
picked_candidate = _get_best_alias_from_candidates(alias, candidates)
|
66
|
+
if not picked_candidate:
|
67
|
+
return None
|
68
|
+
return picked_candidate[0]
|
69
|
+
|
70
|
+
|
71
|
+
def find_problem_by_alias(
|
72
|
+
alias: str, root: Optional[pathlib.Path] = None
|
73
|
+
) -> Optional[DumpedProblem]:
|
74
|
+
metadata_path = find_problem_path_by_alias(alias, root)
|
75
|
+
if not metadata_path:
|
76
|
+
return None
|
77
|
+
return DumpedProblem.model_validate_json(metadata_path.read_text())
|
78
|
+
|
79
|
+
|
80
|
+
def find_problem_by_code(
|
81
|
+
code: str, root: Optional[pathlib.Path] = None
|
82
|
+
) -> Optional[DumpedProblem]:
|
83
|
+
metadata_path = find_problem_path_by_code(code, root)
|
84
|
+
if not metadata_path:
|
85
|
+
return None
|
86
|
+
return DumpedProblem.model_validate_json(metadata_path.read_text())
|
87
|
+
|
88
|
+
|
89
|
+
def find_problem_by_anything(
|
90
|
+
anything: str, root: Optional[pathlib.Path] = None
|
91
|
+
) -> Optional[DumpedProblem]:
|
92
|
+
problem = find_problem_by_code(anything, root)
|
93
|
+
if problem:
|
94
|
+
return problem
|
95
|
+
return find_problem_by_alias(anything, root)
|
96
|
+
|
97
|
+
|
98
|
+
def find_problems(root: Optional[pathlib.Path] = None) -> List[DumpedProblem]:
|
99
|
+
if not root:
|
100
|
+
root = pathlib.Path()
|
101
|
+
|
102
|
+
problems = []
|
103
|
+
for metadata_path in root.glob('*.rbx.json'):
|
104
|
+
problems.append(DumpedProblem.model_validate_json(metadata_path.read_text()))
|
105
|
+
return problems
|
@@ -0,0 +1,43 @@
|
|
1
|
+
from typing import List
|
2
|
+
|
3
|
+
from rbx.providers.codeforces import CodeforcesProvider
|
4
|
+
from rbx.providers.provider import ProviderInterface
|
5
|
+
from rbx.schema import Problem
|
6
|
+
|
7
|
+
ALL_PROVIDERS: List[ProviderInterface] = [
|
8
|
+
CodeforcesProvider(),
|
9
|
+
]
|
10
|
+
|
11
|
+
|
12
|
+
def is_contest(problems: List[Problem]) -> bool:
|
13
|
+
for provider in ALL_PROVIDERS:
|
14
|
+
handle_all = all(provider.should_handle(problem.url) for problem in problems)
|
15
|
+
if handle_all:
|
16
|
+
return provider.is_contest(problems)
|
17
|
+
return False
|
18
|
+
|
19
|
+
|
20
|
+
def should_simplify_contest_problems(problems: List[Problem]) -> bool:
|
21
|
+
if not is_contest(problems):
|
22
|
+
return False
|
23
|
+
for provider in ALL_PROVIDERS:
|
24
|
+
handle_all = all(provider.should_handle(problem.url) for problem in problems)
|
25
|
+
if handle_all:
|
26
|
+
return provider.should_simplify_contest_problems()
|
27
|
+
return False
|
28
|
+
|
29
|
+
|
30
|
+
def get_code(problem: Problem, simplify: bool = False) -> str:
|
31
|
+
for provider in ALL_PROVIDERS:
|
32
|
+
if provider.should_handle(problem.url):
|
33
|
+
if simplify:
|
34
|
+
return provider.get_problem_code_within_contest(problem)
|
35
|
+
return provider.get_code(problem)
|
36
|
+
return problem.get_normalized_name()
|
37
|
+
|
38
|
+
|
39
|
+
def get_aliases(problem: Problem) -> List[str]:
|
40
|
+
for provider in ALL_PROVIDERS:
|
41
|
+
if provider.should_handle(problem.url):
|
42
|
+
return provider.get_aliases(problem)
|
43
|
+
return []
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import re
|
2
|
+
from typing import List, Optional
|
3
|
+
|
4
|
+
from rbx.providers.provider import ProviderInterface
|
5
|
+
from rbx.schema import Problem
|
6
|
+
|
7
|
+
|
8
|
+
def _add_underscores(matches: List[str]) -> List[str]:
|
9
|
+
if len(matches) <= 2:
|
10
|
+
return matches
|
11
|
+
return [f'{x}_' for x in matches[:-2]] + matches[-2:]
|
12
|
+
|
13
|
+
|
14
|
+
_PATTERNS = [
|
15
|
+
r'https?://(?:.*\.)?codeforces.(?:com|ml|es)/(?:contest|gym)/(\d+)/problem/([^/]+)',
|
16
|
+
r'https?://(?:.*\.)?codeforces.(?:com|ml|es)/problemset/problem/(\d+)/([^/]+)',
|
17
|
+
(
|
18
|
+
r'https?://(?:.*\.)?codeforces.(?:com|ml|es)/group/([^/]+)/contest/(\d+)/problem/([^/]+)',
|
19
|
+
_add_underscores,
|
20
|
+
),
|
21
|
+
r'https?://(?:.*\.)?codeforces.(?:com|ml|es)/problemset/(gym)Problem/([^/]+)',
|
22
|
+
r'https?://(?:.*\.)?codeforces.(?:com|ml|es)/problemsets/(acm)sguru/problem/(?:\d+)/([^/]+)',
|
23
|
+
# TODO: add EDU
|
24
|
+
]
|
25
|
+
|
26
|
+
|
27
|
+
def _compiled_pattern(pattern):
|
28
|
+
if isinstance(pattern, tuple):
|
29
|
+
return (re.compile(pattern[0]), pattern[1])
|
30
|
+
return re.compile(pattern)
|
31
|
+
|
32
|
+
|
33
|
+
_COMPILED_PATTERNS = [_compiled_pattern(pattern) for pattern in _PATTERNS]
|
34
|
+
|
35
|
+
|
36
|
+
def get_code_tuple(url: str) -> Optional[List[str]]:
|
37
|
+
for pattern_obj in _COMPILED_PATTERNS:
|
38
|
+
if isinstance(pattern_obj, tuple):
|
39
|
+
pattern, extract = pattern_obj
|
40
|
+
else:
|
41
|
+
pattern = pattern_obj
|
42
|
+
extract = lambda x: x # noqa: E731
|
43
|
+
|
44
|
+
if match := pattern.match(url):
|
45
|
+
return extract(list(match.groups()))
|
46
|
+
return None
|
47
|
+
|
48
|
+
|
49
|
+
class CodeforcesProvider(ProviderInterface):
|
50
|
+
def should_handle(self, url: str) -> bool:
|
51
|
+
return 'codeforces.com/' in url
|
52
|
+
|
53
|
+
def should_simplify_contest_problems(self) -> bool:
|
54
|
+
return True
|
55
|
+
|
56
|
+
def get_problem_code_within_contest(self, problem: Problem) -> str:
|
57
|
+
return self.get_aliases(problem)[-1]
|
58
|
+
|
59
|
+
def get_code(self, problem: Problem) -> str:
|
60
|
+
code_tuple = get_code_tuple(problem.url)
|
61
|
+
if not code_tuple:
|
62
|
+
return super().get_code(problem)
|
63
|
+
return ''.join(code_tuple)
|
64
|
+
|
65
|
+
def get_aliases(self, problem: Problem) -> List[str]:
|
66
|
+
code_tuple = get_code_tuple(problem.url)
|
67
|
+
if not code_tuple:
|
68
|
+
return super().get_aliases(problem)
|
69
|
+
|
70
|
+
aliases = []
|
71
|
+
for i in range(len(code_tuple)):
|
72
|
+
aliases.append(''.join(code_tuple[i:]))
|
73
|
+
return aliases
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import abc
|
2
|
+
from typing import List
|
3
|
+
|
4
|
+
from rbx.schema import Problem
|
5
|
+
|
6
|
+
|
7
|
+
class ProviderInterface(abc.ABC):
|
8
|
+
@abc.abstractmethod
|
9
|
+
def should_handle(self, url: str) -> bool:
|
10
|
+
pass
|
11
|
+
|
12
|
+
def is_contest(self, problems: List[Problem]) -> bool:
|
13
|
+
batches = set(problem.batch.id for problem in problems)
|
14
|
+
return len(batches) == 1
|
15
|
+
|
16
|
+
def should_simplify_contest_problems(self) -> bool:
|
17
|
+
return False
|
18
|
+
|
19
|
+
def get_problem_code_within_contest(self, problem: Problem) -> str:
|
20
|
+
return self.get_code(problem)
|
21
|
+
|
22
|
+
def get_code(self, problem: Problem) -> str:
|
23
|
+
return problem.name
|
24
|
+
|
25
|
+
def get_aliases(self, problem: Problem) -> List[str]:
|
26
|
+
return []
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#include "testlib.h"
|
2
|
+
|
3
|
+
using namespace std;
|
4
|
+
|
5
|
+
int main(int argc, char *argv[]) {
|
6
|
+
setName("custom checker");
|
7
|
+
registerTestlibCmd(argc, argv);
|
8
|
+
|
9
|
+
quitf(_wa, "wrong answer");
|
10
|
+
quitf(_pe, "presentation error");
|
11
|
+
quitf(_ok, "ok");
|
12
|
+
|
13
|
+
inf, ouf, ans;
|
14
|
+
|
15
|
+
inf.readInt();
|
16
|
+
inf.readInts(5);
|
17
|
+
inf.readWord();
|
18
|
+
inf.readDouble();
|
19
|
+
inf.readLong();
|
20
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
{
|
2
|
+
"defaultLanguage": "exinc",
|
3
|
+
"editor": "vim",
|
4
|
+
"languages": {
|
5
|
+
"c++17": {
|
6
|
+
"template": "template.cpp",
|
7
|
+
"file": "%{problem-code}.cpp",
|
8
|
+
"preprocess": [
|
9
|
+
"g++ \"%{file}\" -std=c++17 -fdiagnostics-color=always"
|
10
|
+
],
|
11
|
+
"exec": "./a.out",
|
12
|
+
"artifacts": {
|
13
|
+
"a.out": {
|
14
|
+
"executable": true
|
15
|
+
}
|
16
|
+
},
|
17
|
+
"submitor": "c++17"
|
18
|
+
},
|
19
|
+
"exinc": {
|
20
|
+
"template": "template.cpp",
|
21
|
+
"file": "%{problem-code}.cpp",
|
22
|
+
"submitFile": "%{problem-code}.pre.cpp",
|
23
|
+
"preprocess": [
|
24
|
+
"exinc -i \"%{file}\" -o \"%{submit-file}\" -c"
|
25
|
+
],
|
26
|
+
"exec": "./a.out",
|
27
|
+
"artifacts": {
|
28
|
+
"a.out": {
|
29
|
+
"executable": true
|
30
|
+
}
|
31
|
+
},
|
32
|
+
"submitor": "c++17"
|
33
|
+
}
|
34
|
+
},
|
35
|
+
"submitor": {
|
36
|
+
"c++17": {
|
37
|
+
"codeforces": {
|
38
|
+
"typeid": 54
|
39
|
+
}
|
40
|
+
}
|
41
|
+
},
|
42
|
+
"credentials": {
|
43
|
+
"codeforces": {
|
44
|
+
"handle": "",
|
45
|
+
"password": ""
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
---
|
2
|
+
sandbox: "stupid"
|
3
|
+
defaultCompilation:
|
4
|
+
sandbox:
|
5
|
+
maxProcesses: 1000
|
6
|
+
timeLimit: 10000 # 10 seconds
|
7
|
+
wallTimeLimit: 10000 # 10 seconds
|
8
|
+
memoryLimit: 1024 # 1gb
|
9
|
+
preserveEnv: true
|
10
|
+
mirrorDirs:
|
11
|
+
- "/etc"
|
12
|
+
- "/usr"
|
13
|
+
defaultExecution:
|
14
|
+
sandbox:
|
15
|
+
# Useful for checkers, validators, etc.
|
16
|
+
timeLimit: 10000 # 10 seconds
|
17
|
+
wallTimeLimit: 10000 # 10 seconds
|
18
|
+
memoryLimit: 1024 # 1gb
|
19
|
+
languages:
|
20
|
+
- name: "cpp"
|
21
|
+
readable_name: "C++17"
|
22
|
+
extension: "cpp"
|
23
|
+
compilation:
|
24
|
+
commands:
|
25
|
+
- "g++ -std=c++17 -O2 -o {executable} {compilable}"
|
26
|
+
execution:
|
27
|
+
command: "./{executable}"
|
28
|
+
fileMapping:
|
29
|
+
compilable: "compilable.cpp"
|
30
|
+
- name: "py"
|
31
|
+
readable_name: "Python3"
|
32
|
+
extension: "py"
|
33
|
+
execution:
|
34
|
+
command: "python3 {executable}"
|
35
|
+
fileMapping:
|
36
|
+
executable: "executable.py"
|
37
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
---
|
2
|
+
sandbox: "isolate"
|
3
|
+
defaultCompilation:
|
4
|
+
sandbox:
|
5
|
+
maxProcesses: null
|
6
|
+
timeLimit: null # 10 seconds
|
7
|
+
wallTimeLimit: null # 10 seconds
|
8
|
+
memoryLimit: null # 1gb
|
9
|
+
preserveEnv: true
|
10
|
+
mirrorDirs:
|
11
|
+
- "/etc"
|
12
|
+
- "/usr"
|
13
|
+
defaultExecution:
|
14
|
+
sandbox:
|
15
|
+
# Useful for checkers, validators, etc.
|
16
|
+
timeLimit: 10000 # 10 seconds
|
17
|
+
wallTimeLimit: 10000 # 10 seconds
|
18
|
+
memoryLimit: 1024 # 1gb
|
19
|
+
languages:
|
20
|
+
- name: "cpp"
|
21
|
+
readable_name: "C++17"
|
22
|
+
extension: "cpp"
|
23
|
+
compilation:
|
24
|
+
commands:
|
25
|
+
- "/usr/bin/g++ -std=c++17 -O2 -o {executable} {compilable}"
|
26
|
+
execution:
|
27
|
+
command: "./{executable}"
|
28
|
+
fileMapping:
|
29
|
+
compilable: "compilable.cpp"
|
30
|
+
- name: "py"
|
31
|
+
readable_name: "Python3"
|
32
|
+
extension: "py"
|
33
|
+
execution:
|
34
|
+
command: "/usr/bin/python3 {executable}"
|
35
|
+
fileMapping:
|
36
|
+
executable: "executable.py"
|
37
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
### START OF CHECKER COMPILATION
|
2
|
+
CHECKER_PATH="checker.cpp"
|
3
|
+
CHECKER_OUT="../checker.exe"
|
4
|
+
|
5
|
+
# find compiler
|
6
|
+
cc=`which g++`
|
7
|
+
[ -x "$cc" ] || cc=/usr/bin/g++
|
8
|
+
if [ ! -x "$cc" ]; then
|
9
|
+
echo "$cc not found or it's not executable"
|
10
|
+
exit 47
|
11
|
+
fi
|
12
|
+
read -r -d '' TestlibContent <<"EOF"
|
13
|
+
{{testlib_content}}
|
14
|
+
EOF
|
15
|
+
|
16
|
+
read -r -d '' CheckerContent <<"EOF"
|
17
|
+
{{checker_content}}
|
18
|
+
EOF
|
19
|
+
|
20
|
+
printf "%s" "${TestlibContent}" > testlib.h
|
21
|
+
printf "%s" "${CheckerContent}" > $CHECKER_PATH
|
22
|
+
|
23
|
+
checker_hash=($(md5sum $CHECKER_PATH))
|
24
|
+
checker_cache="/tmp/boca-chk-${checker_hash}"
|
25
|
+
|
26
|
+
echo "Polygon checker hash: $checker_hash"
|
27
|
+
if [ -f "$checker_cache" ]; then
|
28
|
+
echo "Recovering polygon checker from cache: $checker_cache"
|
29
|
+
cp "$checker_cache" $CHECKER_OUT -f
|
30
|
+
else
|
31
|
+
echo "Compiling polygon checker: $CHECKER_PATH"
|
32
|
+
$cc {{stdcpp}} -static -O2 -lm $CHECKER_PATH -o $CHECKER_OUT
|
33
|
+
|
34
|
+
if [ $? -ne 0 ]; then
|
35
|
+
echo "Checker could not be compiled"
|
36
|
+
exit 47
|
37
|
+
fi
|
38
|
+
|
39
|
+
cp $CHECKER_OUT "$checker_cache" -f
|
40
|
+
fi
|
41
|
+
|
42
|
+
chmod 0755 $CHECKER_OUT
|
43
|
+
### END OF CHECKER COMPILATION
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# ////////////////////////////////////////////////////////////////////////////////
|
3
|
+
# //BOCA Online Contest Administrator
|
4
|
+
# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com)
|
5
|
+
# //
|
6
|
+
# // This program is free software: you can redistribute it and/or modify
|
7
|
+
# // it under the terms of the GNU General Public License as published by
|
8
|
+
# // the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# // (at your option) any later version.
|
10
|
+
# //
|
11
|
+
# // This program is distributed in the hope that it will be useful,
|
12
|
+
# // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# // GNU General Public License for more details.
|
15
|
+
# // You should have received a copy of the GNU General Public License
|
16
|
+
# // along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
# ////////////////////////////////////////////////////////////////////////////////
|
18
|
+
# // Last modified 21/jul/2012 by cassio@ime.usp.br
|
19
|
+
#
|
20
|
+
# This script receives:
|
21
|
+
# $1 team_output
|
22
|
+
# $2 sol_output
|
23
|
+
# $3 problem_input (might be used by some specific checkers, here it is not)
|
24
|
+
#
|
25
|
+
# BOCA reads the last line of the standard output
|
26
|
+
# and pass it to judges
|
27
|
+
#
|
28
|
+
if [ ! -r "$1" -o ! -r "$2" ]; then
|
29
|
+
echo "Parameter problem"
|
30
|
+
exit 43
|
31
|
+
fi
|
32
|
+
|
33
|
+
# Next lines of this script just compares team_output and sol_output,
|
34
|
+
# although it is possible to change them to more complex evaluations.
|
35
|
+
output=`../checker.exe $3 $1 $2 2>&1 >/dev/null`
|
36
|
+
EC=$?
|
37
|
+
|
38
|
+
echo "checker exitcode = $EC"
|
39
|
+
echo "$output"
|
40
|
+
|
41
|
+
if [ $EC -eq 0 ]; then
|
42
|
+
echo "checker found no differences"
|
43
|
+
exit 4
|
44
|
+
elif [ $EC -eq 1 ]; then
|
45
|
+
echo "checker found differences"
|
46
|
+
exit 6
|
47
|
+
elif [ $EC -eq 2 ]; then
|
48
|
+
echo "checker failed"
|
49
|
+
exit 5
|
50
|
+
elif [ $EC -ne 3 ]; then
|
51
|
+
echo "unkown compare error $EC"
|
52
|
+
exit 43
|
53
|
+
fi
|