rbx.cp 0.5.73__py3-none-any.whl → 0.6.1__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.
Files changed (86) hide show
  1. rbx/annotations.py +21 -1
  2. rbx/box/cd.py +11 -1
  3. rbx/box/checkers.py +9 -1
  4. rbx/box/cli.py +59 -46
  5. rbx/box/code.py +142 -3
  6. rbx/box/contest/build_contest_statements.py +44 -34
  7. rbx/box/contest/contest_package.py +4 -7
  8. rbx/box/contest/main.py +7 -58
  9. rbx/box/contest/schema.py +52 -8
  10. rbx/box/contest/statements.py +53 -25
  11. rbx/box/creation.py +3 -36
  12. rbx/box/environment.py +21 -9
  13. rbx/box/fields.py +35 -0
  14. rbx/box/lang.py +27 -0
  15. rbx/box/linting.py +26 -0
  16. rbx/box/package.py +4 -35
  17. rbx/box/packaging/boca/packager.py +48 -5
  18. rbx/box/packaging/contest_main.py +13 -0
  19. rbx/box/packaging/main.py +13 -2
  20. rbx/box/packaging/packager.py +4 -4
  21. rbx/box/packaging/pkg/packager.py +142 -0
  22. rbx/box/packaging/polygon/packager.py +2 -24
  23. rbx/box/packaging/polygon/upload.py +35 -17
  24. rbx/box/presets/__init__.py +362 -281
  25. rbx/box/presets/lock_schema.py +1 -2
  26. rbx/box/presets/schema.py +13 -5
  27. rbx/box/remote.py +2 -2
  28. rbx/box/retries.py +8 -0
  29. rbx/box/schema.py +82 -19
  30. rbx/box/solutions.py +77 -15
  31. rbx/box/statements/build_statements.py +44 -27
  32. rbx/box/statements/builders.py +18 -10
  33. rbx/box/statements/expander.py +49 -0
  34. rbx/box/statements/latex_jinja.py +61 -4
  35. rbx/box/statements/schema.py +33 -9
  36. rbx/box/stats.py +92 -0
  37. rbx/box/tasks.py +6 -3
  38. rbx/box/testcase_utils.py +19 -47
  39. rbx/box/tooling/__init__.py +0 -0
  40. rbx/box/tooling/boca/__init__.py +0 -0
  41. rbx/box/tooling/boca/main.py +13 -0
  42. rbx/box/tooling/boca/scrape.py +34 -0
  43. rbx/box/{packaging/boca/upload.py → tooling/boca/scraper.py} +77 -8
  44. rbx/box/tooling/main.py +8 -0
  45. rbx/box/ui/utils/run_ui.py +1 -1
  46. rbx/box/ui/widgets/interaction_box.py +19 -1
  47. rbx/grading/caching.py +18 -2
  48. rbx/grading/judge/sandbox.py +60 -5
  49. rbx/grading/judge/sandboxes/isolate.py +1 -0
  50. rbx/grading/judge/sandboxes/stupid_sandbox.py +11 -5
  51. rbx/grading/judge/sandboxes/timeit.py +36 -15
  52. rbx/grading/processing_context.py +62 -78
  53. rbx/grading/steps.py +92 -40
  54. rbx/resources/packagers/boca/checker.sh +4 -1
  55. rbx/resources/packagers/boca/compile/c +2 -6
  56. rbx/resources/packagers/boca/compile/cc +2 -6
  57. rbx/resources/packagers/boca/compile/cpp +2 -6
  58. rbx/resources/packagers/boca/compile/java +1 -6
  59. rbx/resources/packagers/boca/compile/kt +24 -28
  60. rbx/resources/packagers/boca/compile/py2 +2 -6
  61. rbx/resources/packagers/boca/compile/py3 +2 -6
  62. rbx/resources/packagers/boca/interactive/c +15 -83
  63. rbx/resources/packagers/boca/interactive/cc +15 -83
  64. rbx/resources/packagers/boca/interactive/cpp +15 -83
  65. rbx/resources/packagers/boca/interactive/java +15 -88
  66. rbx/resources/packagers/boca/interactive/kt +15 -88
  67. rbx/resources/packagers/boca/interactive/py2 +15 -88
  68. rbx/resources/packagers/boca/interactive/py3 +15 -88
  69. rbx/resources/packagers/boca/interactor_compile.sh +5 -2
  70. rbx/resources/packagers/boca/interactor_run.sh +174 -0
  71. rbx/resources/packagers/boca/safeexec.c +530 -0
  72. rbx/resources/packagers/boca/safeexec_compile.sh +49 -0
  73. rbx/resources/presets/default/contest/contest.rbx.yml +9 -8
  74. rbx/resources/presets/default/problem/problem.rbx.yml +38 -26
  75. rbx/resources/presets/default/problem/random.txt +3 -1
  76. rbx/resources/presets/default/problem/rbx.h +92 -0
  77. rbx/resources/presets/default/problem/statement/statement.rbx.tex +4 -7
  78. rbx/resources/presets/default/problem/validator.cpp +8 -8
  79. rbx/resources/templates/rbx.h +2 -3
  80. {rbx_cp-0.5.73.dist-info → rbx_cp-0.6.1.dist-info}/METADATA +23 -6
  81. {rbx_cp-0.5.73.dist-info → rbx_cp-0.6.1.dist-info}/RECORD +84 -71
  82. {rbx_cp-0.5.73.dist-info → rbx_cp-0.6.1.dist-info}/WHEEL +1 -1
  83. rbx/resources/packagers/boca/compile/pas +0 -172
  84. rbx/resources/presets/default/problem/statement/projecao.png +0 -0
  85. {rbx_cp-0.5.73.dist-info → rbx_cp-0.6.1.dist-info}/LICENSE +0 -0
  86. {rbx_cp-0.5.73.dist-info → rbx_cp-0.6.1.dist-info}/entry_points.txt +0 -0
@@ -1,87 +1,71 @@
1
- import asyncio
2
1
  import contextlib
3
2
  import os
4
3
  import signal
5
- import threading
6
- from typing import Optional, Set
4
+ import subprocess
5
+ from typing import List, Optional
7
6
 
8
- _processing_context_pids: Optional[Set[int]] = None
9
- _terminate_all_on_error = False
10
- _lock = threading.Lock()
11
-
12
- # Creating a processing context is not thread-safe, but adding to it is.
7
+ from rbx.grading.judge.sandbox import SandboxBase
13
8
 
14
9
 
15
10
  @contextlib.contextmanager
16
- def new_processing_context(terminate_all_on_error: bool = False):
17
- global _processing_context_pids, _terminate_all_on_error
18
- with _lock:
19
- old_processing_context_pids = _processing_context_pids
20
- _old_terminate_all_on_error = _terminate_all_on_error
21
- _processing_context_pids = set()
22
- _terminate_all_on_error = terminate_all_on_error
11
+ def new_process_group():
12
+ p = subprocess.Popen(['/bin/bash', '-c', 'exec sleep infinity'])
23
13
  try:
24
- yield
14
+ yield p.pid
25
15
  finally:
26
- with _lock:
27
- _processing_context_pids = old_processing_context_pids
28
- _terminate_all_on_error = _old_terminate_all_on_error
29
-
30
-
31
- def get_processing_context() -> Set[int]:
32
- with _lock:
33
- return _processing_context_pids or set()
34
-
35
-
36
- def add_to_processing_context(pid: int):
37
- global _processing_context_pids
38
- with _lock:
39
- if _processing_context_pids is None:
40
- return
41
- _processing_context_pids.add(pid)
42
-
43
-
44
- def terminate_all_processes_in_context(clear: bool = True):
45
- global _processing_context_pids
46
- with _lock:
47
- if _processing_context_pids is None:
48
- return
49
- for pid in _processing_context_pids:
50
- try:
51
- os.kill(pid, signal.SIGTERM)
52
- except OSError:
53
- pass
54
- if clear:
55
- _processing_context_pids.clear()
56
-
57
-
58
- async def wait_all_processes_in_context(wait_for: int):
59
- global _processing_context_pids, _terminate_all_on_error
60
- wait_pids = set()
61
- while len(get_processing_context()) < wait_for:
62
- await asyncio.sleep(0.01)
63
-
64
- with _lock:
65
- if _processing_context_pids is None:
66
- return
67
- wait_pids.update(_processing_context_pids)
68
-
69
- wait_lock = threading.Lock()
70
- finished_pids = []
71
-
72
- def process(pid: int, returncode: int):
73
- with wait_lock:
74
- finished_pids.append(pid)
75
- if returncode != 0 and _terminate_all_on_error:
76
- terminate_all_processes_in_context()
77
-
78
- def wait_all_processes():
79
- while len(finished_pids) < len(wait_pids):
80
- try:
81
- pid, status = os.wait()
82
- except ChildProcessError:
83
- return
84
- if pid in wait_pids:
85
- process(pid, os.waitstatus_to_exitcode(status))
86
-
87
- await asyncio.to_thread(wait_all_processes)
16
+ p.terminate()
17
+ p.wait()
18
+
19
+
20
+ def should_use_group(sandboxes: List[SandboxBase]) -> bool:
21
+ if not sandboxes:
22
+ return False
23
+ uses_pgid = all(sandbox.use_pgid() for sandbox in sandboxes)
24
+ all_pgids = set(
25
+ sandbox.params.pgid for sandbox in sandboxes if sandbox.params.pgid is not None
26
+ )
27
+ return uses_pgid and len(all_pgids) == 1
28
+
29
+
30
+ async def _fetch_pids(sandboxes: List[SandboxBase]) -> List[int]:
31
+ return [await sandbox.get_pid() for sandbox in sandboxes]
32
+
33
+
34
+ def _find_sandbox_idx(pids: List[int], pid: int) -> Optional[int]:
35
+ try:
36
+ return pids.index(pid)
37
+ except ValueError:
38
+ return None
39
+
40
+
41
+ async def _wait_for_group(sandboxes: List[SandboxBase]) -> List[int]:
42
+ pgid = [
43
+ sandbox.params.pgid for sandbox in sandboxes if sandbox.params.pgid is not None
44
+ ][0]
45
+ assert pgid is not None
46
+
47
+ sandbox_pids = await _fetch_pids(sandboxes)
48
+
49
+ finished = []
50
+ while len(finished) < len(sandboxes):
51
+ try:
52
+ pid, status = os.waitpid(-pgid, 0)
53
+ except ChildProcessError:
54
+ break
55
+
56
+ if os.waitstatus_to_exitcode(status) != 0:
57
+ os.kill(pgid, signal.SIGKILL)
58
+
59
+ sandbox_idx = _find_sandbox_idx(sandbox_pids, pid)
60
+ if sandbox_idx is not None:
61
+ finished.append(sandbox_idx)
62
+ continue
63
+
64
+ return finished
65
+
66
+
67
+ async def wait_all(sandboxes: List[SandboxBase]):
68
+ if not should_use_group(sandboxes):
69
+ raise RuntimeError('Sandboxes are not using a process group')
70
+
71
+ await _wait_for_group(sandboxes)
rbx/grading/steps.py CHANGED
@@ -10,7 +10,6 @@ import shutil
10
10
  import subprocess
11
11
  import sys
12
12
  import tempfile
13
- import typing
14
13
  from enum import Enum
15
14
  from typing import IO, Any, Dict, Iterable, List, Optional, Tuple, Union
16
15
 
@@ -53,6 +52,27 @@ class Outcome(Enum):
53
52
  Outcome.IDLENESS_LIMIT_EXCEEDED,
54
53
  ]
55
54
 
55
+ def short_name(self) -> str:
56
+ if self == Outcome.ACCEPTED:
57
+ return 'AC'
58
+ if self == Outcome.WRONG_ANSWER:
59
+ return 'WA'
60
+ if self == Outcome.TIME_LIMIT_EXCEEDED:
61
+ return 'TLE'
62
+ if self == Outcome.IDLENESS_LIMIT_EXCEEDED:
63
+ return 'ILE'
64
+ if self == Outcome.MEMORY_LIMIT_EXCEEDED:
65
+ return 'MLE'
66
+ if self == Outcome.RUNTIME_ERROR:
67
+ return 'RTE'
68
+ if self == Outcome.OUTPUT_LIMIT_EXCEEDED:
69
+ return 'OLE'
70
+ if self == Outcome.JUDGE_FAILED:
71
+ return 'FL'
72
+ if self == Outcome.INTERNAL_ERROR:
73
+ return 'IE'
74
+ return 'XX'
75
+
56
76
 
57
77
  class DigestHolder(BaseModel):
58
78
  value: Optional[str] = None
@@ -372,12 +392,12 @@ def _is_c_command(exe_command: str) -> bool:
372
392
  return 'gcc' in exe_command or 'clang' in exe_command
373
393
 
374
394
 
375
- def _is_cpp_command(exe_command: str) -> bool:
395
+ def is_cpp_command(exe_command: str) -> bool:
376
396
  return 'g++' in exe_command or 'clang++' in exe_command
377
397
 
378
398
 
379
399
  def is_cxx_command(exe_command: str) -> bool:
380
- return _is_cpp_command(exe_command) or _is_c_command(exe_command)
400
+ return is_cpp_command(exe_command) or _is_c_command(exe_command)
381
401
 
382
402
 
383
403
  def is_cxx_sanitizer_command(command: str) -> bool:
@@ -413,7 +433,8 @@ def _complain_about_clang() -> None:
413
433
  )
414
434
 
415
435
 
416
- def _get_cxx_version_output(command: str) -> Optional[str]:
436
+ @functools.cache
437
+ def _get_cxx_version_output(command: str, extra_flags: str = '') -> Optional[str]:
417
438
  cmds = shlex.split(command)
418
439
  if not cmds:
419
440
  return None
@@ -421,8 +442,8 @@ def _get_cxx_version_output(command: str) -> Optional[str]:
421
442
  if not is_cxx_command(exe):
422
443
  return None
423
444
 
424
- exe = cmds[0]
425
- output = subprocess.run([exe, '-v'], capture_output=True)
445
+ extra = shlex.split(extra_flags)
446
+ output = subprocess.run([exe, '-v', *extra], capture_output=True, input='')
426
447
  if output.returncode != 0:
427
448
  console.print('[error]Failed to get C/C++ compiler version.[/error]')
428
449
  return None
@@ -430,6 +451,8 @@ def _get_cxx_version_output(command: str) -> Optional[str]:
430
451
 
431
452
 
432
453
  def _maybe_get_bits_stdcpp_for_clang(command: str) -> Optional[GradingFileInput]:
454
+ if not is_cpp_command(get_exe_from_command(command)):
455
+ return None
433
456
  version_output = _get_cxx_version_output(command)
434
457
  if version_output is None:
435
458
  return None
@@ -446,11 +469,44 @@ def _maybe_get_bits_stdcpp_for_clang(command: str) -> Optional[GradingFileInput]
446
469
  return GradingFileInput(src=bits, dest=pathlib.Path('bits/stdc++.h'))
447
470
 
448
471
 
449
- def _maybe_get_bits_stdcpp_for_commands(
472
+ def _find_system_paths_in_version_output(version_output: str) -> List[pathlib.Path]:
473
+ res = []
474
+ start = False
475
+ for line in version_output.splitlines():
476
+ if line.startswith('#include <...> search starts here:'):
477
+ start = True
478
+ continue
479
+ if not start:
480
+ continue
481
+ if not line.startswith(' '):
482
+ break
483
+ res.append(pathlib.Path(line.strip()))
484
+ return res
485
+
486
+
487
+ def _get_system_bits_stdcpp(command: str) -> Optional[GradingFileInput]:
488
+ if not is_cpp_command(get_exe_from_command(command)):
489
+ return None
490
+ version_output = _get_cxx_version_output(command, '-xc++ -E -')
491
+ if version_output is None:
492
+ return None
493
+ for path in _find_system_paths_in_version_output(version_output):
494
+ bits_candidate = path / 'bits' / 'stdc++.h'
495
+ if not bits_candidate.is_file():
496
+ continue
497
+ return GradingFileInput(
498
+ src=bits_candidate.resolve().absolute(), dest=pathlib.Path('bits/stdc++.h')
499
+ )
500
+ return None
501
+
502
+
503
+ def maybe_get_bits_stdcpp_for_commands(
450
504
  commands: List[str],
451
505
  ) -> Optional[GradingFileInput]:
452
506
  for command in commands:
453
- res = _maybe_get_bits_stdcpp_for_clang(command)
507
+ res = _get_system_bits_stdcpp(command) or _maybe_get_bits_stdcpp_for_clang(
508
+ command
509
+ )
454
510
  if res is not None:
455
511
  return res
456
512
  return None
@@ -560,10 +616,9 @@ def compile(
560
616
  sandbox: SandboxBase,
561
617
  artifacts: GradingArtifacts,
562
618
  ) -> bool:
619
+ sandbox.reset()
620
+
563
621
  commands = _try_following_alias_for_commands(commands)
564
- bits_artifact = _maybe_get_bits_stdcpp_for_commands(commands)
565
- if bits_artifact is not None:
566
- _process_input_artifacts(GradingArtifacts(inputs=[bits_artifact]), sandbox)
567
622
  _process_input_artifacts(artifacts, sandbox)
568
623
 
569
624
  if not commands:
@@ -571,7 +626,9 @@ def compile(
571
626
  return True
572
627
 
573
628
  logs: List[PreprocessLog] = []
574
- sandbox.set_params(params)
629
+ sandbox.set_params(
630
+ params.model_copy(deep=True)
631
+ ) # Copy to allow further modification.
575
632
 
576
633
  for i, command in enumerate(commands):
577
634
  _maybe_complain_about_sanitization(command)
@@ -584,10 +641,6 @@ def compile(
584
641
  if is_java_like_command(get_exe_from_command(command)):
585
642
  sandbox.params.address_space = None
586
643
 
587
- if bits_artifact is not None and _is_cpp_command(cmd[0]):
588
- # Include from sandbox directory to import bits/stdc++.h.
589
- cmd.append('-I.')
590
-
591
644
  if not sandbox.execute_without_std(cmd):
592
645
  console.print(
593
646
  '[error]Sandbox crashed while processing command:[/error]',
@@ -642,17 +695,21 @@ async def run(
642
695
  sandbox: SandboxBase,
643
696
  artifacts: GradingArtifacts,
644
697
  metadata: Optional[RunLogMetadata] = None,
645
- kill_on_processing_context_exit: bool = False,
646
698
  ) -> Optional[RunLog]:
699
+ sandbox.reset()
700
+
647
701
  _process_input_artifacts(artifacts, sandbox)
648
702
  _process_fifos(artifacts, sandbox)
649
703
  cmd = _split_and_expand(command, sandbox)
650
- sandbox.set_params(params)
704
+ sandbox.set_params(
705
+ params.model_copy(deep=True)
706
+ ) # Copy to allow further modification.
651
707
 
652
708
  # Remove memory constraints for Java.
653
709
  if is_java_like_command(get_exe_from_command(command)):
654
710
  sandbox.params.address_space = None
655
711
 
712
+ sandbox.pid_event.set_loop(asyncio.get_event_loop())
656
713
  if not await asyncio.to_thread(sandbox.execute_without_std, cmd):
657
714
  console.print(
658
715
  '[error]Sandbox crashed while processing command:[/error]',
@@ -662,9 +719,6 @@ async def run(
662
719
  )
663
720
  return None
664
721
 
665
- if sandbox.get_exit_code() != 0 and kill_on_processing_context_exit:
666
- processing_context.terminate_all_processes_in_context(clear=False)
667
-
668
722
  if not _process_output_artifacts(artifacts, sandbox):
669
723
  return None
670
724
 
@@ -706,27 +760,25 @@ async def run_coordinated(
706
760
  interactor: CoordinatedRunParams,
707
761
  solution: CoordinatedRunParams,
708
762
  ) -> Tuple[Optional[RunLog], Optional[RunLog]]:
709
- with processing_context.new_processing_context(terminate_all_on_error=True):
710
- # Schedule both runs to execute immediately.
711
- runs = tuple(
712
- asyncio.create_task(
713
- run(
714
- params.command,
715
- params.params,
716
- params.sandbox,
717
- params.artifacts,
718
- params.metadata,
719
- kill_on_processing_context_exit=True,
720
- )
763
+ def run_one(params: CoordinatedRunParams) -> asyncio.Task[Optional[RunLog]]:
764
+ return asyncio.create_task(
765
+ run(
766
+ params.command,
767
+ params.params,
768
+ params.sandbox,
769
+ params.artifacts,
770
+ params.metadata,
721
771
  )
722
- for params in [interactor, solution]
723
- )
724
- await processing_context.wait_all_processes_in_context(wait_for=2)
725
- logs = typing.cast(
726
- Tuple[Optional[RunLog], Optional[RunLog]],
727
- tuple(await asyncio.gather(*runs)),
728
772
  )
729
- return logs
773
+
774
+ # Use interactor PID as the process group id.
775
+ interactor_task = run_one(interactor)
776
+ solution.sandbox.params.pgid = await interactor.sandbox.get_pid()
777
+ solution_task = run_one(solution)
778
+
779
+ await processing_context.wait_all([interactor.sandbox, solution.sandbox])
780
+
781
+ return await asyncio.gather(interactor_task, solution_task)
730
782
 
731
783
 
732
784
  def _normalize_checked_words(s: str) -> Tuple[str, ...]:
@@ -1,4 +1,7 @@
1
1
  ### START OF CHECKER COMPILATION
2
+ CACHE_DIR="/tmp/boca-cache"
3
+ mkdir -p $CACHE_DIR
4
+
2
5
  CDIR=$(pwd)
3
6
  CHECKER_PATH="checker.cpp"
4
7
  CHECKER_OUT="checker.exe"
@@ -27,7 +30,7 @@ printf "%s" "${RbxHeaderContent}" >rbx.h
27
30
  printf "%s" "${CheckerContent}" >$CHECKER_PATH
28
31
 
29
32
  checker_hash=($(cat $CHECKER_PATH rbx.h testlib.h | md5sum))
30
- checker_cache="/tmp/boca-chk-${checker_hash}"
33
+ checker_cache="$CACHE_DIR/checker-${checker_hash}"
31
34
 
32
35
  echo "Polygon checker hash: $checker_hash"
33
36
  echo "Copying polygon checker to $CDIR/$CHECKER_OUT"
@@ -92,12 +92,8 @@ if [ "$4" != "" ]; then
92
92
  fi
93
93
 
94
94
  # setting up the timelimit according to the problem
95
- if [ "$3" == "" ]; then
96
- time=5
97
- else
98
- time=$3
99
- fi
100
- let "ttime = $time + 30"
95
+ time=15
96
+ let "ttime = $time * 2"
101
97
 
102
98
  if [ "$2" == "" ]; then
103
99
  exe=run.exe
@@ -93,12 +93,8 @@ if [ "$4" != "" ]; then
93
93
  fi
94
94
 
95
95
  # setting up the timelimit according to the problem
96
- if [ "$3" == "" ]; then
97
- time=5
98
- else
99
- time=$3
100
- fi
101
- let "ttime = $time + 30"
96
+ time=15
97
+ let "ttime = $time * 2"
102
98
 
103
99
  if [ "$2" == "" ]; then
104
100
  exe=run.exe
@@ -92,12 +92,8 @@ if [ "$4" != "" ]; then
92
92
  fi
93
93
 
94
94
  # setting up the timelimit according to the problem
95
- if [ "$3" == "" ]; then
96
- time=5
97
- else
98
- time=$3
99
- fi
100
- let "ttime = $time + 30"
95
+ time=15
96
+ let "ttime = $time * 2"
101
97
 
102
98
  if [ "$2" == "" ]; then
103
99
  exe=run.exe
@@ -88,13 +88,8 @@ if [ ! -x $sf ]; then
88
88
  fi
89
89
 
90
90
  # setting up the timelimit according to the problem
91
- if [ "$3" == "" ]; then
92
- time=5
93
- else
94
- time=$3
95
- fi
96
- let "ttime = $time + 30"
97
91
  time=30
92
+ ttime=30
98
93
 
99
94
  maxm=512
100
95
  if [ "$4" != "" -a "$4" -gt "512" ]; then
@@ -41,22 +41,22 @@
41
41
 
42
42
  umask 0022
43
43
  if [ "$1" == "" ]; then
44
- echo "parameter problem"
45
- exit 43
44
+ echo "parameter problem"
45
+ exit 43
46
46
  fi
47
47
  name="$1"
48
48
  if [ ! -r "$1" ]; then
49
- echo "$1 not found or it's not readable"
50
- exit 44
49
+ echo "$1 not found or it's not readable"
50
+ exit 44
51
51
  fi
52
52
  id -u bocajail >/dev/null 2>/dev/null
53
53
  if [ $? == 0 ]; then
54
- bocau=`id -u bocajail`
55
- bocag=`id -g bocajail`
54
+ bocau=$(id -u bocajail)
55
+ bocag=$(id -g bocajail)
56
56
  chown bocajail.nogroup .
57
57
  else
58
- bocau=`id -u nobody`
59
- bocag=`id -g nobody`
58
+ bocau=$(id -u nobody)
59
+ bocag=$(id -g nobody)
60
60
  chown nobody.nogroup .
61
61
  fi
62
62
  if [ "$bocau" == "" -o "$bocag" == "" ]; then
@@ -67,10 +67,10 @@ fi
67
67
  mkdir -p src
68
68
  if [ "${name##*.}" == "zip" -a "${name##*.}" == "ZIP" ]; then
69
69
  unzip "$name" -d src
70
- if [ "${name##*.}" == "zip" ]; then
71
- name=`basename $name .zip`
70
+ if [ "${name##*.}" == "zip" ]; then
71
+ name=$(basename $name .zip)
72
72
  else
73
- name=`basename $name .ZIP`
73
+ name=$(basename $name .ZIP)
74
74
  fi
75
75
  else
76
76
  cp "$name" src
@@ -80,42 +80,38 @@ chmod -R 700 src
80
80
 
81
81
  # this script makes use of safeexec to execute the code with less privilegies
82
82
  # make sure that directories below are correct.
83
- sf=`which safeexec`
83
+ sf=$(which safeexec)
84
84
  [ -x "$sf" ] || sf=/usr/bin/safeexec
85
85
  if [ ! -x $sf ]; then
86
- echo "$sf not found or it's not executable"
87
- exit 46
86
+ echo "$sf not found or it's not executable"
87
+ exit 46
88
88
  fi
89
89
 
90
90
  # setting up the timelimit according to the problem
91
- if [ "$3" == "" ]; then
92
- time=5
93
- else
94
- time=$3
95
- fi
96
- let "ttime = $time + 30"
91
+ time=30
92
+ ttime=30
97
93
 
98
94
  maxm=1024
99
95
  if [ "$4" != "" -a "$4" -gt "1024" ]; then
100
- maxm=$4
96
+ maxm=$4
101
97
  fi
102
98
 
103
99
  maxms=100
104
100
 
105
101
  if [ "$2" == "" ]; then
106
- jarfile=run.jar
102
+ jarfile=run.jar
107
103
  else
108
- jarfile=$2
104
+ jarfile=$2
109
105
  fi
110
106
 
111
- cdir=`pwd`
107
+ cdir=$(pwd)
112
108
  echo "Current directory is $cdir" >&2
113
- mainname=`echo $name | cut -d'.' -f1`
109
+ mainname=$(echo $name | cut -d'.' -f1)
114
110
  if [ "$mainname" == "" ]; then
115
- mainname=Main
111
+ mainname=Main
116
112
  fi
117
113
 
118
- cat <<EOF > compileit.sh
114
+ cat <<EOF >compileit.sh
119
115
  #!/bin/bash
120
116
  kotlinc=/snap/kotlin/24/bin/kotlinc
121
117
  [ -x "\$kotlinc" ] || kotlinc=/snap/bin/kotlinc
@@ -147,7 +143,7 @@ if [ "$ret" != "0" ]; then
147
143
  echo "Compilation Error: $ret"
148
144
  exit $ret
149
145
  fi
150
- ret=`cat compileit.retcode`
146
+ ret=$(cat compileit.retcode)
151
147
  if [ "$ret" != "0" ]; then
152
148
  echo "Compilation Error: $ret"
153
149
  ret=1
@@ -92,12 +92,8 @@ if [ "$4" != "" ]; then
92
92
  fi
93
93
 
94
94
  # setting up the timelimit according to the problem
95
- if [ "$3" == "" ]; then
96
- time=5
97
- else
98
- time=$3
99
- fi
100
- let "ttime = $time + 30"
95
+ time=15
96
+ let "ttime = $time * 2"
101
97
 
102
98
  if [ "$2" == "" ]; then
103
99
  exe=run.exe
@@ -92,12 +92,8 @@ if [ "$4" != "" ]; then
92
92
  fi
93
93
 
94
94
  # setting up the timelimit according to the problem
95
- if [ "$3" == "" ]; then
96
- time=5
97
- else
98
- time=$3
99
- fi
100
- let "ttime = $time + 30"
95
+ time=15
96
+ let "ttime = $time * 2"
101
97
 
102
98
  if [ "$2" == "" ]; then
103
99
  exe=run.exe