diff --git a/.github/skills/ctf-testing/test_ctf_challenges.sh b/.github/skills/ctf-testing/test_ctf_challenges.sh index 9a43c52..25a29dc 100644 --- a/.github/skills/ctf-testing/test_ctf_challenges.sh +++ b/.github/skills/ctf-testing/test_ctf_challenges.sh @@ -147,7 +147,7 @@ if [[ -f "${REBOOT_MARKER}" ]]; then EXPECTED=$(cat "$PROGRESS_SNAPSHOT") ACTUAL=$(sort -u /var/ctf/completed_challenges 2>/dev/null | wc -l) if [ "$ACTUAL" -ge "$EXPECTED" ]; then - _pass "Progress persisted after reboot ($ACTUAL challenges)" + _pass "Progress persisted after reboot ($ACTUAL checks)" else _fail "Progress lost after reboot (expected ${EXPECTED}, got ${ACTUAL})" fi @@ -192,6 +192,12 @@ else exit 1 fi +if echo "${VERIFY_OUTPUT}" | grep -q "1/19"; then + _pass "verify progress counts the example check" +else + _fail "verify progress did not show 1/19 after the example check" +fi + if [[ -f /var/ctf/ctf_start_time ]]; then _pass "Timer starts after first numeric verify command" else @@ -580,10 +586,10 @@ fi _section "VERIFICATION TOKEN TEST" PROGRESS=$(verify progress 2>&1) -if echo "${PROGRESS}" | grep -q "18/18"; then - _pass "All 18 challenges completed" +if echo "${PROGRESS}" | grep -q "19/19"; then + _pass "All 19 progress checks completed" else - _fail "Not all challenges completed: ${PROGRESS}" + _fail "Not all progress checks completed: ${PROGRESS}" fi EXPORT_OUT=$(verify export testuser 2>&1) || true diff --git a/README.md b/README.md index 0084325..11d1008 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,9 @@ Save the token it generates — you'll need it to verify your progress at [learn - `verify time` shows **wall clock elapsed time** (not active keyboard time). - The timer starts when you first submit a challenge with `verify `. -- The timer freezes on your first successful `verify export` after reaching 18/18. -- Run `verify 0 CTF{example}` early. The example challenge is part of verify progress tracking. +- Progress tracks 19 total checks: the example verification plus the 18 real challenges. +- After `verify 0 CTF{example}`, `verify progress` should show `1/19`. +- The timer freezes on your first successful `verify export` after you've solved all 18 real challenges. ### Troubleshooting Your Token diff --git a/gcp/README.md b/gcp/README.md index 318649b..6fb0b8b 100644 --- a/gcp/README.md +++ b/gcp/README.md @@ -53,7 +53,7 @@ ## Timer Behavior -`verify time` uses wall clock elapsed time. The timer starts on your first challenge submission and freezes on your first successful `verify export` after 18/18. +`verify time` uses wall clock elapsed time. The timer starts on your first challenge submission and freezes on your first successful `verify export` after you've solved all 18 real challenges. ## Cleaning Up diff --git a/verify/src/verify/commands.py b/verify/src/verify/commands.py index a25bc1a..a53b05f 100644 --- a/verify/src/verify/commands.py +++ b/verify/src/verify/commands.py @@ -68,15 +68,25 @@ ] -def completed_count() -> int: +EXAMPLE_CHALLENGE_NUMBER = 0 +MAX_CHALLENGE_NUMBER = len(CHALLENGE_NAMES) - 1 +REAL_CHALLENGE_COUNT = MAX_CHALLENGE_NUMBER +TOTAL_PROGRESS_CHECKS = len(CHALLENGE_NAMES) + + +def completed_progress_count() -> int: + return len(read_completed()) + + +def completed_challenge_count() -> int: completed = read_completed() - return max(len(completed - {0}), 0) + return max(len(completed - {EXAMPLE_CHALLENGE_NUMBER}), 0) def show_progress() -> None: - count = completed_count() - console.print(f"Flags Found: {count}/18") - if count == 18: + count = completed_progress_count() + console.print(f"Flags Found: {count}/{TOTAL_PROGRESS_CHECKS}") + if count == TOTAL_PROGRESS_CHECKS: console.print("Congratulations! You've completed all challenges!") @@ -98,7 +108,7 @@ def elapsed_seconds() -> int | None: def freeze_end_time_on_export() -> None: if END_TIME_FILE.exists(): return - if completed_count() >= 18: + if completed_challenge_count() >= REAL_CHALLENGE_COUNT: END_TIME_FILE.write_text(f"{int(time.time())}\n") END_TIME_FILE.chmod(0o666) @@ -114,8 +124,8 @@ def format_elapsed(seconds: int, *, include_seconds: bool) -> str: def check_flag(state: CtfState, challenge_num: str, submitted_flag: str) -> int: init_timer() - if not challenge_num.isdigit() or not 0 <= int(challenge_num) <= 18: - console.print("✗ Invalid challenge number. Use 0-18.") + if not challenge_num.isdigit() or not 0 <= int(challenge_num) <= MAX_CHALLENGE_NUMBER: + console.print(f"✗ Invalid challenge number. Use 0-{MAX_CHALLENGE_NUMBER}.") return 1 num = int(challenge_num) @@ -158,8 +168,8 @@ def show_list() -> int: def show_hint(num_text: str | None) -> int: - if num_text is None or not num_text.isdigit() or int(num_text) > 18: - console.print("Usage: verify hint [0-18]") + if num_text is None or not num_text.isdigit() or int(num_text) > MAX_CHALLENGE_NUMBER: + console.print(f"Usage: verify hint [0-{MAX_CHALLENGE_NUMBER}]") return 1 num = int(num_text) console.print("======================================") @@ -171,10 +181,10 @@ def show_hint(num_text: str | None) -> int: def export_certificate(state: CtfState, github_username: str | None) -> int: - count = completed_count() - if count < 18: - console.print("Complete all 18 challenges to earn your certificate!") - console.print(f"Current progress: {count}/18") + count = completed_challenge_count() + if count < REAL_CHALLENGE_COUNT: + console.print(f"Complete all {REAL_CHALLENGE_COUNT} challenges to earn your certificate!") + console.print(f"Current progress: {count}/{REAL_CHALLENGE_COUNT}") return 1 if not github_username: