rbx.cp 0.5.1__tar.gz → 0.5.3__tar.gz

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.
Files changed (163) hide show
  1. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/PKG-INFO +1 -1
  2. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/pyproject.toml +1 -1
  3. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/main.py +3 -0
  4. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/packaging/boca/extension.py +3 -3
  5. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/packaging/boca/packager.py +41 -5
  6. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/stresses.py +5 -12
  7. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/stressing/finder_parser.py +83 -24
  8. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/checker.sh +2 -2
  9. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/problem.rbx.yml +1 -1
  10. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/LICENSE +0 -0
  11. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/README.md +0 -0
  12. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/__init__.py +0 -0
  13. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/annotations.py +0 -0
  14. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/autoenum.py +0 -0
  15. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/__init__.py +0 -0
  16. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/builder.py +0 -0
  17. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/cd.py +0 -0
  18. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/checkers.py +0 -0
  19. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/code.py +0 -0
  20. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/compile.py +0 -0
  21. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/conftest.py +0 -0
  22. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/contest/__init__.py +0 -0
  23. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/contest/build_contest_statements.py +0 -0
  24. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/contest/contest_package.py +0 -0
  25. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/contest/contest_utils.py +0 -0
  26. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/contest/main.py +0 -0
  27. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/contest/schema.py +0 -0
  28. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/contest/statements.py +0 -0
  29. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/creation.py +0 -0
  30. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/download.py +0 -0
  31. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/environment.py +0 -0
  32. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/extensions.py +0 -0
  33. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/generators.py +0 -0
  34. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/generators_test.py +0 -0
  35. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/package.py +0 -0
  36. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/packaging/contest_main.py +0 -0
  37. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/packaging/main.py +0 -0
  38. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/packaging/packager.py +0 -0
  39. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/packaging/polygon/packager.py +0 -0
  40. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/packaging/polygon/test.py +0 -0
  41. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/packaging/polygon/xml_schema.py +0 -0
  42. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/presets/__init__.py +0 -0
  43. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/presets/fetch.py +0 -0
  44. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/presets/lock_schema.py +0 -0
  45. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/presets/schema.py +0 -0
  46. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/schema.py +0 -0
  47. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/solutions.py +0 -0
  48. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/solutions_test.py +0 -0
  49. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/statements/__init__.py +0 -0
  50. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/statements/build_statements.py +0 -0
  51. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/statements/builders.py +0 -0
  52. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/statements/joiners.py +0 -0
  53. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/statements/latex.py +0 -0
  54. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/statements/latex_jinja.py +0 -0
  55. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/statements/schema.py +0 -0
  56. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/stressing/__init__.py +0 -0
  57. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/stressing/generator_parser.py +0 -0
  58. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/testcases.py +0 -0
  59. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/ui/__init__.py +0 -0
  60. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/ui/captured_log.py +0 -0
  61. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/ui/css/app.tcss +0 -0
  62. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/ui/main.py +0 -0
  63. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/ui/run.py +0 -0
  64. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/validators.py +0 -0
  65. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/box/validators_test.py +0 -0
  66. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/checker.py +0 -0
  67. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/clone.py +0 -0
  68. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/config.py +0 -0
  69. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/conftest.py +0 -0
  70. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/console.py +0 -0
  71. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/create.py +0 -0
  72. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/edit.py +0 -0
  73. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/__init__.py +0 -0
  74. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/caching.py +0 -0
  75. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/conftest.py +0 -0
  76. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/judge/__init__.py +0 -0
  77. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/judge/cacher.py +0 -0
  78. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/judge/digester.py +0 -0
  79. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/judge/sandbox.py +0 -0
  80. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/judge/sandboxes/__init__.py +0 -0
  81. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/judge/sandboxes/isolate.py +0 -0
  82. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/judge/sandboxes/stupid_sandbox.py +0 -0
  83. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/judge/sandboxes/timeit.py +0 -0
  84. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/judge/storage.py +0 -0
  85. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/judge/test.py +0 -0
  86. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/judge/testiso.py +0 -0
  87. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/steps.py +0 -0
  88. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/steps_with_caching.py +0 -0
  89. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading/steps_with_caching_run_test.py +0 -0
  90. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/grading_utils.py +0 -0
  91. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/hydration.py +0 -0
  92. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/main.py +0 -0
  93. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/metadata.py +0 -0
  94. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/providers/__init__.py +0 -0
  95. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/providers/codeforces.py +0 -0
  96. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/providers/provider.py +0 -0
  97. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/checkers/boilerplate.cpp +0 -0
  98. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/default_config.json +0 -0
  99. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/envs/default.rbx.yml +0 -0
  100. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/envs/isolate.rbx.yml +0 -0
  101. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/compare +0 -0
  102. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/compile/c +0 -0
  103. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/compile/cc +0 -0
  104. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/compile/cpp +0 -0
  105. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/compile/java +0 -0
  106. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/compile/kt +0 -0
  107. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/compile/pas +0 -0
  108. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/compile/py2 +0 -0
  109. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/compile/py3 +0 -0
  110. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/run/c +0 -0
  111. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/run/cc +0 -0
  112. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/run/cpp +0 -0
  113. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/run/java +0 -0
  114. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/run/kt +0 -0
  115. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/run/py2 +0 -0
  116. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/packagers/boca/run/py3 +0 -0
  117. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/contest/contest.rbx.yml +0 -0
  118. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/contest/statement/contest.rbx.tex +0 -0
  119. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/contest/statement/olymp.sty +0 -0
  120. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/contest/statement/template.rbx.tex +0 -0
  121. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/preset.rbx.yml +0 -0
  122. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/.gitignore +0 -0
  123. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/gen.cpp +0 -0
  124. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/random.py +0 -0
  125. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/random.txt +0 -0
  126. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/sols/main.cpp +0 -0
  127. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/sols/slow.cpp +0 -0
  128. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/sols/wa.cpp +0 -0
  129. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/statement/olymp.sty +0 -0
  130. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/statement/projecao.png +0 -0
  131. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/statement/statement.rbx.tex +0 -0
  132. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/statement/template.rbx.tex +0 -0
  133. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/tests/samples/000.in +0 -0
  134. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/tests/samples/001.in +0 -0
  135. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/validator.cpp +0 -0
  136. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/presets/default/problem/wcmp.cpp +0 -0
  137. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/resources/templates/template.cpp +0 -0
  138. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/run.py +0 -0
  139. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/schema.py +0 -0
  140. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/submit.py +0 -0
  141. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/submitors/__init__.py +0 -0
  142. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/submitors/codeforces.py +0 -0
  143. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/submitors/submitor.py +0 -0
  144. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/test.py +0 -0
  145. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testcase.py +0 -0
  146. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testcase_rendering.py +0 -0
  147. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/gen1.cpp +0 -0
  148. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/gen2.cpp +0 -0
  149. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/genScript.py +0 -0
  150. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/hard-tle.sol.cpp +0 -0
  151. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/ole.cpp +0 -0
  152. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/problem.rbx.yml +0 -0
  153. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/re.sol.cpp +0 -0
  154. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/sol.cpp +0 -0
  155. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/tests/1.in +0 -0
  156. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/tle-and-incorrect.sol.cpp +0 -0
  157. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/tle.sol.cpp +0 -0
  158. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/validator.cpp +0 -0
  159. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/box1/wa.sol.cpp +0 -0
  160. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/caching/executable.py +0 -0
  161. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testdata/compatible +0 -0
  162. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/testing_utils.py +0 -0
  163. {rbx_cp-0.5.1 → rbx_cp-0.5.3}/rbx/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: rbx.cp
3
- Version: 0.5.1
3
+ Version: 0.5.3
4
4
  Summary:
5
5
  Author: Roberto Sales
6
6
  Requires-Python: >=3.9,<4.0
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "rbx.cp"
3
- version = "0.5.1"
3
+ version = "0.5.3"
4
4
  description = ""
5
5
  packages = [
6
6
  {include = "rbx"}
@@ -363,6 +363,9 @@ def environment_command(
363
363
  if env is None:
364
364
  cfg = config.get_config()
365
365
  console.console.print(f'Current environment: [item]{cfg.boxEnvironment}[/item]')
366
+ console.console.print(
367
+ f'Location: {environment.get_environment_path(cfg.boxEnvironment)}'
368
+ )
366
369
  return
367
370
  if install_from is not None:
368
371
  environment.install_environment(env, pathlib.Path(install_from))
@@ -14,9 +14,9 @@ class BocaExtension(BaseModel):
14
14
 
15
15
  def flags_with_defaults(self) -> typing.Dict[BocaLanguage, str]:
16
16
  res: typing.Dict[BocaLanguage, str] = {
17
- 'c': '-std=gnu11 -O2 -static -lm',
18
- 'cpp': '-O2 -static -lm',
19
- 'cc': '-std=c++20 -O2 -static -lm',
17
+ 'c': '-std=gnu11 -O2 -lm -static',
18
+ 'cpp': '-O2 -lm -static',
19
+ 'cc': '-std=c++20 -O2 -lm -static',
20
20
  }
21
21
  res.update(self.flags)
22
22
  return res
@@ -48,13 +48,13 @@ class BocaPackager(BasePackager):
48
48
 
49
49
  def _get_problem_name(self) -> str:
50
50
  pkg = package.find_problem_package_or_die()
51
- return pkg.name
51
+ # BOCA forces Java class names to be the name of the problem.
52
+ return pkg.name.replace('-', '_')
52
53
 
53
54
  def _get_problem_info(self) -> str:
54
- pkg = package.find_problem_package_or_die()
55
55
  statement = self._get_main_statement()
56
56
  return (
57
- f'basename={pkg.name}\n'
57
+ f'basename={self._get_problem_name()}\n'
58
58
  f'fullname={statement.title}\n'
59
59
  f'descfile={self._get_problem_name()}.pdf\n'
60
60
  )
@@ -128,6 +128,8 @@ class BocaPackager(BasePackager):
128
128
  return compare_path.read_text()
129
129
 
130
130
  def _get_checker(self) -> str:
131
+ extension = get_extension_or_default('boca', BocaExtension)
132
+
131
133
  checker_path = get_default_app_path() / 'packagers' / 'boca' / 'checker.sh'
132
134
  if not checker_path.exists():
133
135
  console.console.print(
@@ -137,8 +139,10 @@ class BocaPackager(BasePackager):
137
139
  checker_text = checker_path.read_text()
138
140
  testlib = get_testlib().read_text()
139
141
  checker = package.get_checker().path.read_text()
140
- return checker_text.replace('{{testlib_content}}', testlib).replace(
141
- '{{checker_content}}', checker
142
+ return (
143
+ checker_text.replace('{{rbxFlags}}', extension.flags_with_defaults()['cc'])
144
+ .replace('{{testlib_content}}', testlib)
145
+ .replace('{{checker_content}}', checker)
142
146
  )
143
147
 
144
148
  def _get_compile(self, language: BocaLanguage) -> str:
@@ -165,6 +169,33 @@ class BocaPackager(BasePackager):
165
169
  compile_text = compile_text.replace('{{rbxFlags}}', flags[language])
166
170
  return compile_text
167
171
 
172
+ def _copy_solutions(self, into_path: pathlib.Path):
173
+ for solution in package.get_solutions():
174
+ dest_path = (
175
+ into_path
176
+ / solution.path.stem
177
+ / pathlib.Path(self._get_problem_name()).with_suffix(
178
+ solution.path.suffix
179
+ )
180
+ )
181
+ dest_path.parent.mkdir(parents=True, exist_ok=True)
182
+ shutil.copy(str(solution.path), dest_path)
183
+
184
+ if solution.path.suffix == '.java':
185
+ java_content = dest_path.read_text()
186
+ if (
187
+ 'class Main ' not in java_content
188
+ and f'class {self._get_problem_name()} ' not in java_content
189
+ ):
190
+ console.console.print(
191
+ '[error]For BOCA packaging, Java solutions must be named `class Main` or `class <ProblemName>`.[/error]'
192
+ )
193
+ dest_path.write_text(
194
+ java_content.replace(
195
+ 'class Main ', f'class {self._get_problem_name()} '
196
+ )
197
+ )
198
+
168
199
  def name(self) -> str:
169
200
  return 'boca'
170
201
 
@@ -223,6 +254,11 @@ class BocaPackager(BasePackager):
223
254
  (description_path / self._get_problem_name()).with_suffix('.pdf'),
224
255
  )
225
256
 
257
+ # Copy solutions
258
+ solutions_path = into_path / 'solutions'
259
+ solutions_path.mkdir(parents=True, exist_ok=True)
260
+ self._copy_solutions(solutions_path)
261
+
226
262
  # Prepare IO
227
263
  inputs_path = into_path / 'input'
228
264
  inputs_path.mkdir(parents=True, exist_ok=True)
@@ -1,4 +1,3 @@
1
- import dataclasses
2
1
  import functools
3
2
  import time
4
3
  from shutil import rmtree
@@ -175,11 +174,13 @@ def run_stress(
175
174
 
176
175
  @functools.cache
177
176
  def run_solution_and_checker_fn(
178
- solution: str,
179
- checker: Optional[finder_parser.FinderChecker],
177
+ call: finder_parser.FinderCall,
180
178
  input_path=input_path,
181
179
  expected_output_path=expected_output_path,
182
180
  ) -> finder_parser.FinderResult:
181
+ solution = call.solution
182
+ checker = call.checker
183
+
183
184
  solution_result = run_solution_fn(solution)
184
185
 
185
186
  if checker is None:
@@ -196,19 +197,11 @@ def run_stress(
196
197
  solution=solution,
197
198
  outcome=checker_result.outcome,
198
199
  checker=checker,
199
- truth_value=True,
200
200
  solution_result=solution_result,
201
201
  checker_result=checker_result,
202
202
  )
203
203
 
204
- def run_fn(
205
- call: finder_parser.FinderCall,
206
- ) -> finder_parser.FinderResult:
207
- finder_result = run_solution_and_checker_fn(call.solution, call.checker)
208
- truth_value = call.expected_outcome.match(finder_result.outcome)
209
- return dataclasses.replace(finder_result, truth_value=truth_value)
210
-
211
- runner = finder_parser.FinderTreeRunner(runner=run_fn)
204
+ runner = finder_parser.FinderTreeRunner(runner=run_solution_and_checker_fn)
212
205
  finder_outcome: finder_parser.FinderOutcome = runner.transform(parsed_finder)
213
206
 
214
207
  internal_error_results = [
@@ -2,7 +2,7 @@ import dataclasses
2
2
  import pathlib
3
3
  import typing
4
4
  from enum import Enum
5
- from typing import Callable, List, Optional
5
+ from typing import Callable, List, Optional, Union
6
6
 
7
7
  import lark
8
8
  import typer
@@ -20,23 +20,34 @@ disjunction: conjunction | disjunction _OR conjunction
20
20
 
21
21
  conjunction: _atom | conjunction _AND _atom
22
22
 
23
- _atom: statement | "(" disjunction ")" | negation
23
+ _atom: logical | "(" disjunction ")" | negation
24
24
  negation: _NOT "(" disjunction ")"
25
25
 
26
- statement: solution matcher outcome checking?
26
+ // Expressions
27
+ logical: eval matcher expected_outcome -> matching
28
+ | eval equality (eval | outcome) -> equating
27
29
 
30
+ eval: "[" solution checking? "]"
31
+
32
+ // Eval
28
33
  solution: _filename | WILDCARD
29
- outcome: CNAME
30
34
  checking: "ON"i (checking_mode? checker | ":nil")
31
35
  checking_mode: MODE ":"
32
36
  MODE: "2" | "3"
33
37
  checker: _filename | WILDCARD
34
38
 
39
+ // Outcomes
40
+ expected_outcome: CNAME
41
+ outcome: CNAME
42
+
35
43
  // Operators
36
44
  matcher: MATCHES | NOT_MATCHES
45
+ equality: EQUALS | NOT_EQUALS
37
46
 
38
47
  MATCHES: "~"
39
48
  NOT_MATCHES: "!~"
49
+ EQUALS: "=="
50
+ NOT_EQUALS: "!="
40
51
  _OR: "||"
41
52
  _AND: "&&"
42
53
  _NOT: "!"
@@ -46,7 +57,14 @@ WILDCARD: "$"
46
57
  _filename: FILENAME | "\"" FILENAME "\""
47
58
  FILENAME: /[\/A-Za-z0-9\-_\.]/+
48
59
 
49
- %import common.CNAME
60
+ // Names (Variables)
61
+ LCASE_LETTER: "a".."z"
62
+ UCASE_LETTER: "A".."Z"
63
+ DIGIT: "0".."9"
64
+ LETTER: UCASE_LETTER | LCASE_LETTER
65
+ WORD: LETTER+
66
+ CNAME: ("_"|LETTER) ("_"|LETTER|DIGIT|"+")*
67
+
50
68
  %ignore " "
51
69
  """
52
70
 
@@ -67,7 +85,6 @@ class FinderChecker:
67
85
  @dataclasses.dataclass(frozen=True)
68
86
  class FinderCall:
69
87
  solution: str
70
- expected_outcome: ExpectedOutcome
71
88
  checker: Optional[FinderChecker]
72
89
 
73
90
 
@@ -83,7 +100,6 @@ class FinderResult:
83
100
  solution: str
84
101
  outcome: Outcome
85
102
  checker: Optional[FinderChecker]
86
- truth_value: bool
87
103
 
88
104
  # Auxiliary information.
89
105
  solution_result: Optional[FinderSolutionResult] = None
@@ -155,8 +171,8 @@ def _get_checker_from_token(token: lark.Token) -> str:
155
171
  return path
156
172
 
157
173
 
158
- def _get_statement_checker(statement: lark.ParseTree) -> Optional[FinderChecker]:
159
- checking_nodes = list(statement.find_data('checking'))
174
+ def _get_eval_checker(eval: lark.ParseTree) -> Optional[FinderChecker]:
175
+ checking_nodes = list(eval.find_data('checking'))
160
176
  if not checking_nodes:
161
177
  return _get_default_checker_for_finder()
162
178
  (checking,) = checking_nodes
@@ -227,11 +243,11 @@ def get_all_solution_items(tree: lark.ParseTree) -> List[CodeItem]:
227
243
 
228
244
 
229
245
  def _get_all_finder_checkers(tree: lark.ParseTree) -> List[FinderChecker]:
230
- statement_nodes = tree.find_data('statement')
246
+ eval_nodes = tree.find_data('eval')
231
247
  res = []
232
248
 
233
- for statement_node in statement_nodes:
234
- finder_checker = _get_statement_checker(statement_node)
249
+ for eval_node in eval_nodes:
250
+ finder_checker = _get_eval_checker(eval_node)
235
251
  if finder_checker is not None:
236
252
  res.append(finder_checker)
237
253
 
@@ -299,8 +315,6 @@ def validate(tree: lark.ParseTree):
299
315
 
300
316
  @lark.v_args(inline=True)
301
317
  class FinderTreeRunner(lark.Transformer):
302
- outcome = ExpectedOutcome
303
-
304
318
  def __init__(
305
319
  self,
306
320
  runner: Callable[[FinderCall], FinderResult],
@@ -310,27 +324,72 @@ class FinderTreeRunner(lark.Transformer):
310
324
  def solution(self, token: lark.Token) -> str:
311
325
  return _get_solution_from_token(token)
312
326
 
327
+ def outcome(self, token: lark.Token) -> Outcome:
328
+ try:
329
+ outcome = Outcome(token.value)
330
+ except ValueError:
331
+ try:
332
+ expected_outcome = self.expected_outcome(token)
333
+ except ValueError:
334
+ raise ValueError(f'"{token.value}" is not a valid Outcome.') from None
335
+ outcomes = expected_outcome.get_matches()
336
+ if len(outcomes) != 1:
337
+ raise ValueError(
338
+ f'"{token.value}" is not a valid Outcome. You are trying to specify an ExpectedOutcome, instead of a single Outcome.'
339
+ ) from None
340
+ return outcomes[0]
341
+ return outcome
342
+
343
+ def expected_outcome(self, token: lark.Token) -> ExpectedOutcome:
344
+ return ExpectedOutcome(token.value)
345
+
313
346
  def matcher(self, op: lark.Token) -> bool:
314
347
  return op.value == '~'
315
348
 
349
+ def equality(self, op: lark.Token) -> bool:
350
+ return op.value == '=='
351
+
316
352
  @lark.v_args(inline=False, tree=True)
317
- def statement(
353
+ def eval(self, tree: lark.ParseTree) -> FinderResult:
354
+ solution = typing.cast(str, tree.children[0])
355
+ checker: Optional[FinderChecker] = _get_eval_checker(tree)
356
+
357
+ call = FinderCall(solution, checker=checker)
358
+ return self.run_fn(call)
359
+
360
+ def matching(
318
361
  self,
319
- tree: lark.ParseTree,
362
+ eval_result: FinderResult,
363
+ is_positive: bool,
364
+ expected_outcome: ExpectedOutcome,
320
365
  ) -> FinderOutcome:
321
- solution = typing.cast(str, tree.children[0])
322
- is_positive = typing.cast(bool, tree.children[1])
323
- expected_outcome = typing.cast(ExpectedOutcome, tree.children[2])
366
+ truth_value = expected_outcome.match(eval_result.outcome)
367
+ if not is_positive:
368
+ truth_value = not truth_value
369
+
370
+ return FinderOutcome(truth_value=truth_value, results=[eval_result])
371
+
372
+ def equating(
373
+ self,
374
+ eval_result: FinderResult,
375
+ is_positive: bool,
376
+ result_or_outcome: Union[FinderResult, Outcome],
377
+ ) -> FinderOutcome:
378
+ results = [eval_result]
379
+ truth_value = True
324
380
 
325
- checker: Optional[FinderChecker] = _get_statement_checker(tree)
381
+ if isinstance(result_or_outcome, Outcome):
382
+ outcome: Outcome = result_or_outcome
383
+ truth_value = eval_result.outcome == outcome
384
+ else:
385
+ result: FinderResult = result_or_outcome
386
+ truth_value = eval_result.outcome == result.outcome
387
+ results.append(result)
326
388
 
327
- call = FinderCall(solution, expected_outcome=expected_outcome, checker=checker)
328
- result = self.run_fn(call)
329
- truth_value = result.truth_value
330
389
  if not is_positive:
331
390
  truth_value = not truth_value
332
391
 
333
- return FinderOutcome(truth_value=truth_value, results=[result])
392
+ return FinderOutcome(truth_value=truth_value, results=results)
334
393
 
335
394
  def negation(self, value: FinderOutcome) -> FinderOutcome:
336
395
  return dataclasses.replace(value, truth_value=not value.truth_value)
@@ -29,7 +29,7 @@ if [ -f "$checker_cache" ]; then
29
29
  cp "$checker_cache" $CHECKER_OUT -f
30
30
  else
31
31
  echo "Compiling polygon checker: $CHECKER_PATH"
32
- $cc {{stdcpp}} -static -O2 -lm $CHECKER_PATH -o $CHECKER_OUT
32
+ $cc {{rbxFlags}} $CHECKER_PATH -o $CHECKER_OUT
33
33
 
34
34
  if [ $? -ne 0 ]; then
35
35
  echo "Checker could not be compiled"
@@ -40,4 +40,4 @@ else
40
40
  fi
41
41
 
42
42
  chmod 0755 $CHECKER_OUT
43
- ### END OF CHECKER COMPILATION
43
+ ### END OF CHECKER COMPILATION
@@ -38,7 +38,7 @@ stresses:
38
38
  generator:
39
39
  name: 'gen'
40
40
  args: '[1..<MAX_N>] @' # `@` generates a random string
41
- finder: 'sols/wa.cpp ~ INCORRECT'
41
+ finder: '[sols/wa.cpp] ~ INCORRECT'
42
42
  vars:
43
43
  "MAX_N": 1000000000 # Can be used in the validator, in stress tests and in the statement.
44
44
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes