Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bapctools/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
CONSTANT_NAME_REGEX = "[a-zA-Z_][a-zA-Z0-9_]*"
COMPILED_CONSTANT_NAME_REGEX: Final[re.Pattern[str]] = re.compile(CONSTANT_NAME_REGEX)
CONSTANT_SUBSTITUTE_REGEX: Final[re.Pattern[str]] = re.compile(
f"\\{{\\{{({CONSTANT_NAME_REGEX})\\}}\\}}"
f"\\{{\\{{({CONSTANT_NAME_REGEX}|{CONSTANT_NAME_REGEX}\\.{CONSTANT_NAME_REGEX})\\}}\\}}"
)

BAPCTOOLS_SUBSTITUTE_REGEX: Final[re.Pattern[str]] = re.compile(
Expand Down
26 changes: 21 additions & 5 deletions bapctools/problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,11 +326,27 @@ def __init__(
self.constants: dict[str, str] = {}
for key, value in constants.items():
if not isinstance(key, str) or not config.COMPILED_CONSTANT_NAME_REGEX.fullmatch(key):
warn(f"invalid constant name `{key}` for `constants` in problem.yaml. SKIPPED.")
elif not isinstance(value, (str, int, float)):
warn(f"invalid constant type for `constants.{key}` in problem.yaml. SKIPPED.")
else:
self.constants[key] = str(value)
warn(f"invalid name `{key}` for `constants` in problem.yaml. SKIPPED.")
continue

variants = set()
if not isinstance(value, dict):
value = {"value": value}
for sub, variant in value.items():
if not isinstance(sub, str):
warn(f"invalid key `constants.{key}.{sub}` in problem.yaml. SKIPPED.")
elif not config.COMPILED_CONSTANT_NAME_REGEX.fullmatch(sub):
warn(f"invalid key `constants.{key}.{sub}` in problem.yaml. SKIPPED.")
elif not isinstance(variant, (str, int, float)):
warn(f"invalid value for `constants.{key}.{sub}` in problem.yaml. SKIPPED.")
else:
variants.add(str(variant))
self.constants[f"{key}.{sub}"] = str(variant)
if sub == "value":
self.constants[key] = str(variant)

# TODO: check if all variants represent the same value
pass

# BAPCtools extensions:
self.verified: Optional[str] = parser.extract_optional("verified", str)
Expand Down
2 changes: 1 addition & 1 deletion test/problems/constants/generators/example.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/python3
import sys

values = sys.argv[1:] + ["{{INT_FIVE}}", "{{STRING_FIVE}}", "5"]
values = sys.argv[1:] + ["{{FIVE}}", "{{FIVE.value}}", "{{FIVE.INT}}", "{{FIVE.STRING}}", "5"]
assert len(set(values)) == 1
print(values[0])
8 changes: 4 additions & 4 deletions test/problems/constants/generators/generators.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@ solution: /submissions/accepted/submission.py
data:
sample:
data:
- '': example.py {{INT_FIVE}} {{STRING_FIVE}} 5 # substituted
- '': example.py {{FIVE}} {{FIVE.value}} {{FIVE.INT}} {{FIVE.STRING}} 5 # substituted
secret:
include:
- sample

invalid_input:
data:
dont_substitute:
in: "{{INT_FIVE}}" # not substituted
in: "{{FIVE.STRING}}" # not substituted

invalid_answer:
data:
dont_substitute:
in: "5"
ans: "{{INT_FIVE}}" # not substituted
ans: "{{FIVE.STRING}}" # not substituted

invalid_output:
data:
dont_substitute:
in: "5"
ans: "5"
out: "{{INT_FIVE}}" # not substituted
out: "{{FIVE.STRING}}" # not substituted
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

int main(int argc, char** argv) {
InputValidator v(argc, argv);
int n = v.read_integer("n", {{INT_FIVE}}, {{STRING_FIVE}});
int n = v.read_integer("n", {{FIVE.INT}}, {{FIVE.STRING}});
v.newline();
}
2 changes: 1 addition & 1 deletion test/problems/constants/input_validators/validate.ctd
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
INT({{INT_FIVE}}, {{STRING_FIVE}}) NEWLINE
INT({{FIVE.INT}}, {{FIVE.STRING}}) NEWLINE
EOF
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ int main(int argc, char *argv[]) {

int input;
in >> input;
int answer = v.read_integer("answer", {{INT_FIVE}}, {{STRING_FIVE}});
int answer = v.read_integer("answer", {{FIVE.INT}}, {{FIVE.STRING}});
v.newline();
}
8 changes: 6 additions & 2 deletions test/problems/constants/problem.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@ rights_owner: author
# time_limit: 1.0

constants:
INT_FIVE: 5
STRING_FIVE: "5"
FIVE:
value: 5
INT: 5
FLOAT: 5.0
STRING: "5"
SIX: 6
2 changes: 1 addition & 1 deletion test/problems/constants/problem_slide/problem-slide.en.tex
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
\begin{frame}
\frametitle{\problemtitle}

Output a single integer \constant{INT_FIVE}.
Output a single integer \constant{FIVE.STRING}.
\end{frame}
2 changes: 1 addition & 1 deletion test/problems/constants/solution/solution.en.tex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
\begin{frame}
\frametitle{\problemtitle}
Output a single integer \constant{INT_FIVE}.
Output a single integer \constant{FIVE}.
\end{frame}
7 changes: 4 additions & 3 deletions test/problems/constants/statement/problem.en.tex
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
\problemname{}

Output a single integer \constant{STRING_FIVE}.
Output a single integer \constant{FIVE.STRING}.

\begin{Input}
The input consists of:
\begin{itemize}
\item One line with a single integer \constant{INT_FIVE}.
\item One line with a single integer \constant{FIVE.INT}.
\end{itemize}
\end{Input}

\begin{Output}
Output a single integer \constant{INT_FIVE}.
Output a single integer \constant{FIVE}.
Do not print a float like \constant{FIVE.FLOAT}, or any other number like \constant{SIX}.
\end{Output}
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#!/usr/bin/python3
print("{{STRING_FIVE}}")
print("{{FIVE.STRING}}")
Loading