From 0bfee790a8fba9d35292a93b053ba65e5cf2faf6 Mon Sep 17 00:00:00 2001 From: Brian Holman Date: Mon, 9 Nov 2026 20:30:45 -0700 Subject: [PATCH] Add built-in answer tones and automatic multiple-choice progression --- CHATGPT_PROMPT.md | 4 + Makefile | 15 +- README.md | 14 +- docs/FEEDBACK_TESTING.md | 67 ++ docs/TESTING.md | 9 +- docs/evidence/feedback-build-receipt.json | 24 + docs/evidence/feedback-debug-build.json | 24 + docs/evidence/feedback-mc-report.json | 901 ++++++++++++++++++++++ docs/evidence/feedback-release-build.json | 24 + docs/evidence/feedback-release-check.json | 159 ++++ docs/evidence/feedback-typed-report.json | 395 ++++++++++ main.c | 16 +- include/map_data.h => map_data.h | 0 include/quiz.h => quiz.h | 0 tests/playtest_mc.py | 22 +- tests/playtest_typed.py | 3 + tools/prepare_assets.py | 2 +- include/ui.h => ui.h | 0 18 files changed, 1658 insertions(+), 21 deletions(-) create mode 100644 docs/FEEDBACK_TESTING.md create mode 100644 docs/evidence/feedback-build-receipt.json create mode 100644 docs/evidence/feedback-debug-build.json create mode 100644 docs/evidence/feedback-mc-report.json create mode 100644 docs/evidence/feedback-release-build.json create mode 100644 docs/evidence/feedback-release-check.json create mode 100644 docs/evidence/feedback-typed-report.json rename include/map_data.h => map_data.h (100%) rename include/quiz.h => quiz.h (100%) rename include/ui.h => ui.h (100%) diff --git a/CHATGPT_PROMPT.md b/CHATGPT_PROMPT.md index dcea909..05f76c5 100644 --- a/CHATGPT_PROMPT.md +++ b/CHATGPT_PROMPT.md @@ -94,3 +94,7 @@ Verify: Where useful, use verified C-line or function-entry stops and read-only snapshots to inspect quiz state. Use deterministic test seeds for reproducible checks without making ordinary play deterministic. Do not change guest memory or registers to manufacture successful gameplay. Deliver the editable C project in the existing CoCoCapitalQuiz checkout, map assets and credits, runnable binary/disk image, concise build/play instructions, and a clear account of what actually passed or remains untested. + +### Addendum + +Without using any of the extra sound cartridges, please add a positive sound when they get a question right and a negative sound when they get a question wrong. At least in multiple choice, after they answer the question, after a brief delay, go to the next question rather than requiring a key to continue. diff --git a/Makefile b/Makefile index 94c8b85..d3d9fe3 100644 --- a/Makefile +++ b/Makefile @@ -12,8 +12,8 @@ endif ifeq ($(VCC_CONFIGURATION),Test) CPPFLAGS += -DTEST_SEED=2709 endif -CPPFLAGS += -Iinclude -CFLAGS = --coco --intermediate --deps --stack-space=2048 $(OPTIM) +CPPFLAGS += -I. +CFLAGS = --coco --intermediate --stack-space=2048 $(OPTIM) SOURCES = main.c src/quiz.c src/ui.c src/states.c src/map_data.c OBJECTS = $(SOURCES:%.c=obj/%.o) .PHONY: all build disk clean assets test @@ -23,7 +23,8 @@ disk: build/CAPITAL.dsk build/CAPITAL.bin: $(OBJECTS) @mkdir -p build "$(CMOC)" --coco --intermediate --org=2000 --limit=7800 -o $@ $(OBJECTS) -lgime -linput -lbcontrol -lhirestxt -obj/%.o: %.c include/quiz.h include/ui.h include/map_data.h Makefile +# Explicit project headers avoid CMOC .d paths to expired VCC build snapshots. +obj/%.o: %.c quiz.h ui.h map_data.h Makefile @mkdir -p $(dir $@) "$(CMOC)" $(CPPFLAGS) $(CFLAGS) --intdir=$(dir $@) -c -o $@ $< obj/boot.bin: tools/boot.c Makefile @@ -36,10 +37,10 @@ build/CAPITAL.dsk: build/CAPITAL.bin obj/boot.bin assets: python3 tools/prepare_assets.py test: - @mkdir -p build - cc -std=c99 -Wall -Wextra -Werror -DHOST_TEST -Iinclude tests/test_quiz.c src/quiz.c src/states.c -o build/test_quiz - ./build/test_quiz + @set -e; quiz_test_dir=$$(mktemp -d "$${TMPDIR:-/tmp}/capital-quiz-host.XXXXXX"); \ + trap 'rm -rf "$$quiz_test_dir"' EXIT HUP INT TERM; \ + cc -std=c99 -Wall -Wextra -Werror -DHOST_TEST -I. tests/test_quiz.c src/quiz.c src/states.c -o "$$quiz_test_dir/test_quiz"; \ + "$$quiz_test_dir/test_quiz" python3 tests/check_assets.py clean: rm -rf obj build --include $(OBJECTS:.o=.d) diff --git a/README.md b/README.md index 4e61fed..634806a 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,12 @@ Multiple choice: **1–4**. Typed answers: letters/spaces/periods, **Backspace** answer. A near spelling offers **R** to edit the existing answer or **V** to reveal. Only an exact/accepted alias earns a point. A successfully corrected answer earns one point and increments the separate correction count. -Release keys between presses; **Space** advances after feedback. +Both modes play a rising tone for a correct answer and a lower, falling tone +for an incorrect answer, using the CoCo's built-in sound output. No sound +cartridge is needed. Multiple-choice feedback advances automatically after +the tone and a 1.5-second reading pause. In typed mode, **Space** advances after +feedback. Release answer keys before answering the next question; a held key +cannot submit another answer. After all 50 questions: **R** paginated missed-answer review, **N** next review page, **B** results, **P** play again, **Q** return to BASIC. Replay returns to @@ -61,11 +66,14 @@ make test # host logic and geometry checks ``` The editable inputs are `data/states.tsv`, `data/map-seeds.json`, -`assets/usa-source.svg`, `main.c`, `src/quiz.c` and `src/ui.c`. Generated drawing +`assets/usa-source.svg`, `main.c`, `src/quiz.c`, `src/ui.c` and the root-level +`quiz.h`, `ui.h` and `map_data.h` headers. Keeping project headers beside +`main.c` also makes them available to VCC Plus's isolated build snapshots. Generated drawing and state C files are retained for toolchain-only builds. Build outputs are ignored. The public MCP JSON-RPC client in `tools/vcc_mcp.py` takes an exported private grant path; keep that grant outside Git. See [test evidence](docs/TESTING.md) -for actual emulator coverage and limitations, and [credits](assets/CREDITS.md) +for baseline emulator coverage, [feedback tests](docs/FEEDBACK_TESTING.md) +for the sound and automatic-advance checks, and [credits](assets/CREDITS.md) for map attribution and licenses. For the complete public-MCP regression suite, export a private connection with diff --git a/docs/FEEDBACK_TESTING.md b/docs/FEEDBACK_TESTING.md new file mode 100644 index 0000000..51336ee --- /dev/null +++ b/docs/FEEDBACK_TESTING.md @@ -0,0 +1,67 @@ +# Built-in sound and automatic multiple-choice feedback + +Tested in installed VCC Plus 3.5.0 build 41 with its bundled CMOC toolchain, +using the public MCP interface and isolated 512 KB MC6809 workers. + +- Correct answers use a rising pair of BASIC SOUND tones; incorrect answers + use a lower falling pair. Both quiz modes use the built-in audio output. + No Speech/Sound, Orchestra-90 or other sound cartridge is required. +- SOUND executes at normal CPU speed, then restores the faster graphics clock. +- Multiple choice displays correctness and the correct capital, plays its tone, + waits 90 video ticks (1.5 seconds), then advances without a continue key. +- Typed answers retain Space-to-continue. A near spelling still offers retry + or reveal before any result tone or point is awarded. + +## Passed checks + +- Full 50-question multiple-choice run: all states once, numbering 1–50, + unique choices and state highlighting, expected 42/50 (84%), review, replay, + and BASIC exit. No Space or Enter was sent to advance any question. +- An answer key was held across the timeout into Question 2 and for a further + 600 fields. The next question remained unanswered until release/new input. +- Full 50-question typed run: expected 47/50 (94%), two spelling corrections, + casing, aliases, repeated spaces, transpositions, Backspace, long input, + wrong capitals, reveal, review and exit. Feedback remained on Question 1 + after 300 additional idle fields, confirming typed mode still waits for Space. +- Release smoke test: correct and incorrect feedback, a readable pause, + automatic advancement to Questions 2 and 3, expected score, and title Quit. +- Test, Debug and Release builds succeeded without compiler diagnostics. +- Host logic/geometry tests and byte-identical asset regeneration passed. + +## Sound verification and limitation + +The linked CMOC SOUND wrapper calls Color BASIC at $A951. Framebuffer receipts +sampled the emulated PC at $A98C/$A98D during correct and incorrect playback, +confirming execution of the built-in ROM tone path. The public MCP tools do not +export audio samples, so no recording or listening test is claimed. A reusable +VCC enhancement would add field-aligned PCM/WAV capture to disposable playtests +so pitch, duration and silence can be checked without extra cartridges. + +## Files and build details + +Project headers are now quiz.h, ui.h and map_data.h beside main.c. VCC's build +snapshot omitted the nested include directory; root headers build and share +correctly through the documented interface. Make rules and asset generation +use the same layout. Explicit header dependencies replace CMOC dependency files +that could retain expired snapshot paths. Host tests now use a temporary executable +outside the shared checkout. Both a normal and an incremental native build passed +and produced byte-identical copies of the tested Release binary. No emulator or +compiler patch was needed. + +Full PNG captures are in build/evidence/feedback/test and +build/evidence/feedback/release. Complete raw receipts and captures are preserved +in build/evidence/feedback-test.zip and feedback-release.zip. The original +captures remain directly viewable and their full raw evidence is preserved in +build/evidence/baseline.zip. Archives prevent generated JSON receipts from +unnecessarily expanding the assistant's project-sharing scope. Curated receipts +are in docs/evidence/feedback-*.json. + +The Release build is `789DA457-9E69-4746-A833-801EC9F019DA`; artifact +`55C22401-B69A-40A4-9C04-C00281007402`. Code/static storage ends at `$7600`, +below the `$7800` limit, with the separate 2 KiB stack budget unchanged. + +- build/CAPITAL.bin SHA-256: `6e9fd266f3ea0987430e173bf421ab0d8f2a3e9e0359c048050dfeadcf8bfe02` +- build/CAPITAL.dsk SHA-256: `d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f` + +The previous generated binary/disk are preserved in build/previous. All guest +playtests report zero disk writes and used disposable copies of their disks. diff --git a/docs/TESTING.md b/docs/TESTING.md index ea984e5..6ab3d1a 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -1,4 +1,7 @@ -# Test results — 2026-11-09 +# Initial release test results — 2026-11-09 + +For the current sound and automatic-feedback changes, see +[FEEDBACK_TESTING.md](FEEDBACK_TESTING.md). The results below describe the initial release. Built and played with installed **VCC Plus 3.5.0, build 41**, bundled **CMOC 0.1.100**, and the exported **public STDIO MCP interface**. All gameplay ran in disposable @@ -6,7 +9,7 @@ and the exported **public STDIO MCP interface**. All gameplay ran in disposable release fields between presses. No guest memory or registers were modified by a debugger. Personal emulator media and the original running machine were preserved. -## Final source validation +## Initial release validation | Check | Result | | --- | --- | @@ -55,7 +58,7 @@ Full PNG captures and public receipts are in ignored `build/evidence/test/` and The typed report’s answer field records the initial test input when a spelling correction was subsequently made; the captured feedback and score verify the correction. -## Release artifact +## Initial release artifact - Build: `9922B526-537B-4820-BF6C-100EB8846077` - Artifact: `B6BCF288-91C9-43D8-A460-595792BFD457` diff --git a/docs/evidence/feedback-build-receipt.json b/docs/evidence/feedback-build-receipt.json new file mode 100644 index 0000000..db51c90 --- /dev/null +++ b/docs/evidence/feedback-build-receipt.json @@ -0,0 +1,24 @@ +{ + "outputs": [ + { + "bytes": 19254, + "sha256": "33d1727714918e014e9962366f7674989bd932acc469c06c7d9905d3b7920c21", + "path": "build/CAPITAL.bin" + }, + { + "bytes": 161280, + "sha256": "e4a69fd03faa7114f2ccac58262db2ad6fd2e9e656334d6304d52322065ccdf0", + "path": "build/CAPITAL.dsk" + } + ], + "status": "succeeded", + "build_id": "4D9EE084-349D-49BA-A836-8B80DD02CD8A", + "recipe_id": "c6034a96a9c8384f88b88ca833634008438491c73fedf710cf2a4e280ab934b3", + "artifact_id": "C4532AF8-BF4F-4401-9ADC-DDC62D90AC0F", + "revision": 0, + "configuration": "Test", + "action": "disk", + "log": "\"cmoc\" -DTEST_SEED=2709 -I. --coco --intermediate --deps --stack-space=2048 -O2 --intdir=obj/src/ -c -o obj/src/states.o src/states.c\n\"cmoc\" -DTEST_SEED=2709 -I. --coco --intermediate --deps --stack-space=2048 -O2 --intdir=obj/src/ -c -o obj/src/ui.o src/ui.c\n\"cmoc\" -DTEST_SEED=2709 -I. --coco --intermediate --deps --stack-space=2048 -O2 --intdir=obj/src/ -c -o obj/src/quiz.o src/quiz.c\n\"cmoc\" -DTEST_SEED=2709 -I. --coco --intermediate --deps --stack-space=2048 -O2 --intdir=obj/ -c -o obj/main.o main.c\n\"cmoc\" --dos -O0 --limit=2800 -o obj/boot.bin tools/boot.c\n\"cmoc\" -DTEST_SEED=2709 -I. --coco --intermediate --deps --stack-space=2048 -O2 --intdir=obj/src/ -c -o obj/src/map_data.o src/map_data.c\n\"cmoc\" --coco --intermediate --org=2000 --limit=7800 -o build/CAPITAL.bin obj/main.o obj/src/quiz.o obj/src/ui.o obj/src/states.o obj/src/map_data.o -lgime -linput -lbcontrol -lhirestxt\nperl -e 'print chr(255) x (35*18*256)' > build/CAPITAL.dsk\n\"install-coco-boot-loader\" build/CAPITAL.dsk obj/boot.bin\n\"writecocofile\" build/CAPITAL.dsk build/CAPITAL.bin\n", + "project_id": "B89E5EEE-4062-45A7-96F4-4599980CEBAA", + "diagnostics": [] +} \ No newline at end of file diff --git a/docs/evidence/feedback-debug-build.json b/docs/evidence/feedback-debug-build.json new file mode 100644 index 0000000..3155c67 --- /dev/null +++ b/docs/evidence/feedback-debug-build.json @@ -0,0 +1,24 @@ +{ + "status": "succeeded", + "revision": 0, + "recipe_id": "c6034a96a9c8384f88b88ca833634008438491c73fedf710cf2a4e280ab934b3", + "action": "disk", + "artifact_id": "B0AB0E17-A747-414D-8D22-4686A8BB4DFB", + "outputs": [ + { + "bytes": 19297, + "sha256": "624f9d66c325226837888208ba3dbc7555aa3a495035d90da3c9792e5311fd33", + "path": "build/CAPITAL.bin" + }, + { + "path": "build/CAPITAL.dsk", + "bytes": 161280, + "sha256": "1b9b1fa7ad6ae3aca933c005c62c7b142e8efa474e6c1cce0df6a835b01be92b" + } + ], + "configuration": "Debug", + "build_id": "B0EC12B0-412E-4F83-B3F4-76F04D7A34CD", + "log": "\"cmoc\" -I. --coco --intermediate --deps --stack-space=2048 -O2 -fno-omit-frame-pointer --intdir=obj/src/ -c -o obj/src/states.o src/states.c\n\"cmoc\" -I. --coco --intermediate --deps --stack-space=2048 -O2 -fno-omit-frame-pointer --intdir=obj/src/ -c -o obj/src/ui.o src/ui.c\n\"cmoc\" -I. --coco --intermediate --deps --stack-space=2048 -O2 -fno-omit-frame-pointer --intdir=obj/src/ -c -o obj/src/quiz.o src/quiz.c\n\"cmoc\" -I. --coco --intermediate --deps --stack-space=2048 -O2 -fno-omit-frame-pointer --intdir=obj/ -c -o obj/main.o main.c\n\"cmoc\" --dos -O0 --limit=2800 -o obj/boot.bin tools/boot.c\n\"cmoc\" -I. --coco --intermediate --deps --stack-space=2048 -O2 -fno-omit-frame-pointer --intdir=obj/src/ -c -o obj/src/map_data.o src/map_data.c\n\"cmoc\" --coco --intermediate --org=2000 --limit=7800 -o build/CAPITAL.bin obj/main.o obj/src/quiz.o obj/src/ui.o obj/src/states.o obj/src/map_data.o -lgime -linput -lbcontrol -lhirestxt\nperl -e 'print chr(255) x (35*18*256)' > build/CAPITAL.dsk\n\"install-coco-boot-loader\" build/CAPITAL.dsk obj/boot.bin\n\"writecocofile\" build/CAPITAL.dsk build/CAPITAL.bin\n", + "project_id": "B89E5EEE-4062-45A7-96F4-4599980CEBAA", + "diagnostics": [] +} \ No newline at end of file diff --git a/docs/evidence/feedback-mc-report.json b/docs/evidence/feedback-mc-report.json new file mode 100644 index 0000000..088d301 --- /dev/null +++ b/docs/evidence/feedback-mc-report.json @@ -0,0 +1,901 @@ +{ + "score": 42, + "positions": [ + 15, + 15, + 13, + 7 + ], + "questions": [ + { + "question": 1, + "code": "MN", + "state": "Minnesota", + "options": [ + "Saint Paul", + "Des Moines", + "Concord", + "Olympia" + ], + "answer": "Des Moines", + "correct": false, + "score": 0, + "gold_pixels": 265, + "expected_state_pixels": 265, + "field": 2168 + }, + { + "question": 2, + "code": "WV", + "state": "West Virginia", + "options": [ + "Boise", + "Indianapolis", + "Charleston", + "Topeka" + ], + "answer": "Charleston", + "correct": true, + "score": 1, + "gold_pixels": 67, + "expected_state_pixels": 67, + "field": 3584 + }, + { + "question": 3, + "code": "CT", + "state": "Connecticut", + "options": [ + "Boston", + "Olympia", + "Hartford", + "Pierre" + ], + "answer": "Hartford", + "correct": true, + "score": 2, + "gold_pixels": 18, + "expected_state_pixels": 18, + "field": 4392 + }, + { + "question": 4, + "code": "KY", + "state": "Kentucky", + "options": [ + "Frankfort", + "Bismarck", + "Indianapolis", + "Providence" + ], + "answer": "Frankfort", + "correct": true, + "score": 3, + "gold_pixels": 109, + "expected_state_pixels": 109, + "field": 5180 + }, + { + "question": 5, + "code": "FL", + "state": "Florida", + "options": [ + "Tallahassee", + "Charleston", + "Cheyenne", + "Salt Lake City" + ], + "answer": "Tallahassee", + "correct": true, + "score": 4, + "gold_pixels": 204, + "expected_state_pixels": 204, + "field": 5968 + }, + { + "question": 6, + "code": "LA", + "state": "Louisiana", + "options": [ + "Juneau", + "Pierre", + "Baton Rouge", + "Oklahoma City" + ], + "answer": "Baton Rouge", + "correct": true, + "score": 5, + "gold_pixels": 150, + "expected_state_pixels": 150, + "field": 6756 + }, + { + "question": 7, + "code": "WY", + "state": "Wyoming", + "options": [ + "Denver", + "Providence", + "Sacramento", + "Cheyenne" + ], + "answer": "Cheyenne", + "correct": true, + "score": 6, + "gold_pixels": 308, + "expected_state_pixels": 308, + "field": 7564 + }, + { + "question": 8, + "code": "OK", + "state": "Oklahoma", + "options": [ + "Des Moines", + "Oklahoma City", + "Richmond", + "Carson City" + ], + "answer": "Richmond", + "correct": false, + "score": 6, + "gold_pixels": 204, + "expected_state_pixels": 204, + "field": 8352 + }, + { + "question": 9, + "code": "MT", + "state": "Montana", + "options": [ + "Montpelier", + "Helena", + "Little Rock", + "Indianapolis" + ], + "answer": "Helena", + "correct": true, + "score": 7, + "gold_pixels": 473, + "expected_state_pixels": 473, + "field": 9160 + }, + { + "question": 10, + "code": "TX", + "state": "Texas", + "options": [ + "Austin", + "Carson City", + "Montgomery", + "Salem" + ], + "answer": "Austin", + "correct": true, + "score": 8, + "gold_pixels": 913, + "expected_state_pixels": 913, + "field": 9948 + }, + { + "question": 11, + "code": "GA", + "state": "Georgia", + "options": [ + "Madison", + "Lincoln", + "Pierre", + "Atlanta" + ], + "answer": "Atlanta", + "correct": true, + "score": 9, + "gold_pixels": 180, + "expected_state_pixels": 180, + "field": 10736 + }, + { + "question": 12, + "code": "SC", + "state": "South Carolina", + "options": [ + "Springfield", + "Columbia", + "Pierre", + "Atlanta" + ], + "answer": "Columbia", + "correct": true, + "score": 10, + "gold_pixels": 94, + "expected_state_pixels": 94, + "field": 11524 + }, + { + "question": 13, + "code": "NH", + "state": "New Hampshire", + "options": [ + "Concord", + "Austin", + "Richmond", + "Jefferson City" + ], + "answer": "Concord", + "correct": true, + "score": 11, + "gold_pixels": 19, + "expected_state_pixels": 19, + "field": 12332 + }, + { + "question": 14, + "code": "UT", + "state": "Utah", + "options": [ + "Annapolis", + "Salt Lake City", + "Topeka", + "Des Moines" + ], + "answer": "Salt Lake City", + "correct": true, + "score": 12, + "gold_pixels": 263, + "expected_state_pixels": 263, + "field": 13140 + }, + { + "question": 15, + "code": "VA", + "state": "Virginia", + "options": [ + "Bismarck", + "Lansing", + "Richmond", + "Madison" + ], + "answer": "Madison", + "correct": false, + "score": 12, + "gold_pixels": 113, + "expected_state_pixels": 113, + "field": 13928 + }, + { + "question": 16, + "code": "NY", + "state": "New York", + "options": [ + "Salt Lake City", + "Cheyenne", + "Albany", + "Oklahoma City" + ], + "answer": "Albany", + "correct": true, + "score": 13, + "gold_pixels": 134, + "expected_state_pixels": 134, + "field": 14736 + }, + { + "question": 17, + "code": "IL", + "state": "Illinois", + "options": [ + "Bismarck", + "Richmond", + "Springfield", + "Tallahassee" + ], + "answer": "Springfield", + "correct": true, + "score": 14, + "gold_pixels": 173, + "expected_state_pixels": 173, + "field": 15524 + }, + { + "question": 18, + "code": "NV", + "state": "Nevada", + "options": [ + "Carson City", + "Albany", + "Topeka", + "Cheyenne" + ], + "answer": "Carson City", + "correct": true, + "score": 15, + "gold_pixels": 350, + "expected_state_pixels": 350, + "field": 16332 + }, + { + "question": 19, + "code": "RI", + "state": "Rhode Island", + "options": [ + "Honolulu", + "Columbia", + "Topeka", + "Providence" + ], + "answer": "Providence", + "correct": true, + "score": 16, + "gold_pixels": 3, + "expected_state_pixels": 3, + "field": 17120 + }, + { + "question": 20, + "code": "IN", + "state": "Indiana", + "options": [ + "Indianapolis", + "Denver", + "Jefferson City", + "Columbus" + ], + "answer": "Indianapolis", + "correct": true, + "score": 17, + "gold_pixels": 105, + "expected_state_pixels": 105, + "field": 17928 + }, + { + "question": 21, + "code": "MA", + "state": "Massachusetts", + "options": [ + "Indianapolis", + "Albany", + "Boston", + "Montgomery" + ], + "answer": "Boston", + "correct": true, + "score": 18, + "gold_pixels": 21, + "expected_state_pixels": 21, + "field": 18736 + }, + { + "question": 22, + "code": "HI", + "state": "Hawaii", + "options": [ + "Saint Paul", + "Honolulu", + "Bismarck", + "Salt Lake City" + ], + "answer": "Bismarck", + "correct": false, + "score": 18, + "gold_pixels": 20, + "expected_state_pixels": 20, + "field": 19544 + }, + { + "question": 23, + "code": "ME", + "state": "Maine", + "options": [ + "Little Rock", + "Hartford", + "Augusta", + "Helena" + ], + "answer": "Augusta", + "correct": true, + "score": 19, + "gold_pixels": 111, + "expected_state_pixels": 111, + "field": 20332 + }, + { + "question": 24, + "code": "VT", + "state": "Vermont", + "options": [ + "Montpelier", + "Carson City", + "Pierre", + "Richmond" + ], + "answer": "Montpelier", + "correct": true, + "score": 20, + "gold_pixels": 22, + "expected_state_pixels": 22, + "field": 21120 + }, + { + "question": 25, + "code": "CO", + "state": "Colorado", + "options": [ + "Richmond", + "Augusta", + "Pierre", + "Denver" + ], + "answer": "Denver", + "correct": true, + "score": 21, + "gold_pixels": 327, + "expected_state_pixels": 327, + "field": 21908 + }, + { + "question": 26, + "code": "AL", + "state": "Alabama", + "options": [ + "Bismarck", + "Montgomery", + "Salem", + "Austin" + ], + "answer": "Montgomery", + "correct": true, + "score": 22, + "gold_pixels": 155, + "expected_state_pixels": 155, + "field": 22696 + }, + { + "question": 27, + "code": "WI", + "state": "Wisconsin", + "options": [ + "Montgomery", + "Madison", + "Lincoln", + "Saint Paul" + ], + "answer": "Madison", + "correct": true, + "score": 23, + "gold_pixels": 183, + "expected_state_pixels": 183, + "field": 23504 + }, + { + "question": 28, + "code": "AK", + "state": "Alaska", + "options": [ + "Juneau", + "Oklahoma City", + "Jackson", + "Saint Paul" + ], + "answer": "Juneau", + "correct": true, + "score": 24, + "gold_pixels": 266, + "expected_state_pixels": 266, + "field": 24292 + }, + { + "question": 29, + "code": "OH", + "state": "Ohio", + "options": [ + "Sacramento", + "Jefferson City", + "Columbus", + "Santa Fe" + ], + "answer": "Santa Fe", + "correct": false, + "score": 24, + "gold_pixels": 124, + "expected_state_pixels": 124, + "field": 25080 + }, + { + "question": 30, + "code": "MD", + "state": "Maryland", + "options": [ + "Raleigh", + "Atlanta", + "Helena", + "Annapolis" + ], + "answer": "Annapolis", + "correct": true, + "score": 25, + "gold_pixels": 22, + "expected_state_pixels": 22, + "field": 25888 + }, + { + "question": 31, + "code": "MO", + "state": "Missouri", + "options": [ + "Columbus", + "Jefferson City", + "Raleigh", + "Frankfort" + ], + "answer": "Jefferson City", + "correct": true, + "score": 26, + "gold_pixels": 205, + "expected_state_pixels": 205, + "field": 26676 + }, + { + "question": 32, + "code": "PA", + "state": "Pennsylvania", + "options": [ + "Harrisburg", + "Columbia", + "Tallahassee", + "Cheyenne" + ], + "answer": "Harrisburg", + "correct": true, + "score": 27, + "gold_pixels": 138, + "expected_state_pixels": 138, + "field": 27484 + }, + { + "question": 33, + "code": "MS", + "state": "Mississippi", + "options": [ + "Annapolis", + "Jackson", + "Atlanta", + "Denver" + ], + "answer": "Jackson", + "correct": true, + "score": 28, + "gold_pixels": 143, + "expected_state_pixels": 143, + "field": 28292 + }, + { + "question": 34, + "code": "TN", + "state": "Tennessee", + "options": [ + "Nashville", + "Raleigh", + "Oklahoma City", + "Hartford" + ], + "answer": "Nashville", + "correct": true, + "score": 29, + "gold_pixels": 121, + "expected_state_pixels": 121, + "field": 29100 + }, + { + "question": 35, + "code": "KS", + "state": "Kansas", + "options": [ + "Montgomery", + "Providence", + "Topeka", + "Baton Rouge" + ], + "answer": "Topeka", + "correct": true, + "score": 30, + "gold_pixels": 256, + "expected_state_pixels": 256, + "field": 29908 + }, + { + "question": 36, + "code": "NE", + "state": "Nebraska", + "options": [ + "Montpelier", + "Cheyenne", + "Lincoln", + "Harrisburg" + ], + "answer": "Harrisburg", + "correct": false, + "score": 30, + "gold_pixels": 236, + "expected_state_pixels": 236, + "field": 30696 + }, + { + "question": 37, + "code": "WA", + "state": "Washington", + "options": [ + "Olympia", + "Helena", + "Charleston", + "Hartford" + ], + "answer": "Olympia", + "correct": true, + "score": 31, + "gold_pixels": 210, + "expected_state_pixels": 210, + "field": 31504 + }, + { + "question": 38, + "code": "NC", + "state": "North Carolina", + "options": [ + "Olympia", + "Montpelier", + "Helena", + "Raleigh" + ], + "answer": "Raleigh", + "correct": true, + "score": 32, + "gold_pixels": 156, + "expected_state_pixels": 156, + "field": 32312 + }, + { + "question": 39, + "code": "SD", + "state": "South Dakota", + "options": [ + "Pierre", + "Columbia", + "Concord", + "Annapolis" + ], + "answer": "Pierre", + "correct": true, + "score": 33, + "gold_pixels": 243, + "expected_state_pixels": 243, + "field": 33120 + }, + { + "question": 40, + "code": "OR", + "state": "Oregon", + "options": [ + "Salt Lake City", + "Salem", + "Juneau", + "Phoenix" + ], + "answer": "Salem", + "correct": true, + "score": 34, + "gold_pixels": 303, + "expected_state_pixels": 303, + "field": 33928 + }, + { + "question": 41, + "code": "DE", + "state": "Delaware", + "options": [ + "Augusta", + "Annapolis", + "Dover", + "Honolulu" + ], + "answer": "Dover", + "correct": true, + "score": 35, + "gold_pixels": 7, + "expected_state_pixels": 7, + "field": 34716 + }, + { + "question": 42, + "code": "NM", + "state": "New Mexico", + "options": [ + "Albany", + "Indianapolis", + "Santa Fe", + "Olympia" + ], + "answer": "Santa Fe", + "correct": true, + "score": 36, + "gold_pixels": 395, + "expected_state_pixels": 395, + "field": 35504 + }, + { + "question": 43, + "code": "NJ", + "state": "New Jersey", + "options": [ + "Phoenix", + "Trenton", + "Little Rock", + "Jackson" + ], + "answer": "Little Rock", + "correct": false, + "score": 36, + "gold_pixels": 23, + "expected_state_pixels": 23, + "field": 36312 + }, + { + "question": 44, + "code": "ID", + "state": "Idaho", + "options": [ + "Madison", + "Boise", + "Baton Rouge", + "Columbia" + ], + "answer": "Boise", + "correct": true, + "score": 37, + "gold_pixels": 251, + "expected_state_pixels": 251, + "field": 37120 + }, + { + "question": 45, + "code": "IA", + "state": "Iowa", + "options": [ + "Annapolis", + "Harrisburg", + "Hartford", + "Des Moines" + ], + "answer": "Des Moines", + "correct": true, + "score": 38, + "gold_pixels": 172, + "expected_state_pixels": 172, + "field": 37908 + }, + { + "question": 46, + "code": "ND", + "state": "North Dakota", + "options": [ + "Montgomery", + "Bismarck", + "Richmond", + "Charleston" + ], + "answer": "Bismarck", + "correct": true, + "score": 39, + "gold_pixels": 219, + "expected_state_pixels": 219, + "field": 38696 + }, + { + "question": 47, + "code": "MI", + "state": "Michigan", + "options": [ + "Lansing", + "Atlanta", + "Nashville", + "Pierre" + ], + "answer": "Lansing", + "correct": true, + "score": 40, + "gold_pixels": 177, + "expected_state_pixels": 177, + "field": 39504 + }, + { + "question": 48, + "code": "AR", + "state": "Arkansas", + "options": [ + "Little Rock", + "Santa Fe", + "Atlanta", + "Dover" + ], + "answer": "Little Rock", + "correct": true, + "score": 41, + "gold_pixels": 160, + "expected_state_pixels": 160, + "field": 40292 + }, + { + "question": 49, + "code": "AZ", + "state": "Arizona", + "options": [ + "Salt Lake City", + "Phoenix", + "Harrisburg", + "Tallahassee" + ], + "answer": "Phoenix", + "correct": true, + "score": 42, + "gold_pixels": 374, + "expected_state_pixels": 374, + "field": 41100 + }, + { + "question": 50, + "code": "CA", + "state": "California", + "options": [ + "Albany", + "Sacramento", + "Harrisburg", + "Boise" + ], + "answer": "Harrisburg", + "correct": false, + "score": 42, + "gold_pixels": 516, + "expected_state_pixels": 516, + "field": 41888 + } + ], + "run_id": "A1C491C3-7928-49AF-B9DD-697EAA4C16BD", + "artifact": "C4532AF8-BF4F-4401-9ADC-DDC62D90AC0F", + "exit": { + "disk_origin": "verified_artifact", + "disk_sha256": "e4a69fd03faa7114f2ccac58262db2ad6fd2e9e656334d6304d52322065ccdf0", + "machine_frame": 45444, + "frame_number": 45444, + "image_content": true, + "cpu": "6809", + "cycles": 1331035737, + "generation": 2, + "revision": 0, + "remaining_field_budget": 170556, + "field_clock": 45444, + "isolated": true, + "state": "running", + "ram_kb": 512, + "screen_text": "DISK EXTENDED COLOR BASIC 2.1\nCOPR. 1982, 1986 BY TANDY\nUNDER LICENSE FROM MICROSOFT\nAND MICROWARE SYSTEMS CORP.\n\nOK\nDOS\nLOADM\"CAPITAL.BIN\":EXEC\nTHANKS FOR PLAYING CAPITAL QUEST\n!\nOK\n", + "project_id": "B89E5EEE-4062-45A7-96F4-4599980CEBAA", + "boot": 1, + "artifact_id": "C4532AF8-BF4F-4401-9ADC-DDC62D90AC0F", + "remaining_boots": 15, + "height": 480, + "width": 640, + "run_id": "A1C491C3-7928-49AF-B9DD-697EAA4C16BD", + "artifact_disk_sha256": "e4a69fd03faa7114f2ccac58262db2ad6fd2e9e656334d6304d52322065ccdf0", + "pc": 42965, + "disk_dirty": false, + "disk_provenance": { + "origin_artifact_disk_sha256": "e4a69fd03faa7114f2ccac58262db2ad6fd2e9e656334d6304d52322065ccdf0", + "artifact_disk_sha256": "e4a69fd03faa7114f2ccac58262db2ad6fd2e9e656334d6304d52322065ccdf0", + "origin_artifact_id": "C4532AF8-BF4F-4401-9ADC-DDC62D90AC0F", + "artifact_id": "C4532AF8-BF4F-4401-9ADC-DDC62D90AC0F", + "origin": "verified_artifact" + }, + "fields": 45444, + "disk_writes": 0, + "disk_reads": 24576, + "disk_original_sha256": "e4a69fd03faa7114f2ccac58262db2ad6fd2e9e656334d6304d52322065ccdf0" + } +} \ No newline at end of file diff --git a/docs/evidence/feedback-release-build.json b/docs/evidence/feedback-release-build.json new file mode 100644 index 0000000..2e8a3c8 --- /dev/null +++ b/docs/evidence/feedback-release-build.json @@ -0,0 +1,24 @@ +{ + "action": "disk", + "status": "succeeded", + "recipe_id": "c6034a96a9c8384f88b88ca833634008438491c73fedf710cf2a4e280ab934b3", + "build_id": "789DA457-9E69-4746-A833-801EC9F019DA", + "artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "revision": 0, + "configuration": "Release", + "outputs": [ + { + "path": "build/CAPITAL.bin", + "bytes": 19249, + "sha256": "6e9fd266f3ea0987430e173bf421ab0d8f2a3e9e0359c048050dfeadcf8bfe02" + }, + { + "sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "bytes": 161280, + "path": "build/CAPITAL.dsk" + } + ], + "log": "\"cmoc\" -I. --coco --intermediate --deps --stack-space=2048 -O2 --intdir=obj/src/ -c -o obj/src/states.o src/states.c\n\"cmoc\" -I. --coco --intermediate --deps --stack-space=2048 -O2 --intdir=obj/src/ -c -o obj/src/ui.o src/ui.c\n\"cmoc\" -I. --coco --intermediate --deps --stack-space=2048 -O2 --intdir=obj/src/ -c -o obj/src/quiz.o src/quiz.c\n\"cmoc\" -I. --coco --intermediate --deps --stack-space=2048 -O2 --intdir=obj/ -c -o obj/main.o main.c\n\"cmoc\" --dos -O0 --limit=2800 -o obj/boot.bin tools/boot.c\n\"cmoc\" -I. --coco --intermediate --deps --stack-space=2048 -O2 --intdir=obj/src/ -c -o obj/src/map_data.o src/map_data.c\n\"cmoc\" --coco --intermediate --org=2000 --limit=7800 -o build/CAPITAL.bin obj/main.o obj/src/quiz.o obj/src/ui.o obj/src/states.o obj/src/map_data.o -lgime -linput -lbcontrol -lhirestxt\nperl -e 'print chr(255) x (35*18*256)' > build/CAPITAL.dsk\n\"install-coco-boot-loader\" build/CAPITAL.dsk obj/boot.bin\n\"writecocofile\" build/CAPITAL.dsk build/CAPITAL.bin\n", + "project_id": "B89E5EEE-4062-45A7-96F4-4599980CEBAA", + "diagnostics": [] +} \ No newline at end of file diff --git a/docs/evidence/feedback-release-check.json b/docs/evidence/feedback-release-check.json new file mode 100644 index 0000000..777bc46 --- /dev/null +++ b/docs/evidence/feedback-release-check.json @@ -0,0 +1,159 @@ +{ + "artifact": "55C22401-B69A-40A4-9C04-C00281007402", + "run": "A9D3E454-0015-403E-A70C-D191A6143633", + "sound_samples": [ + { + "right": true, + "state": "Wyoming", + "pc": 43404, + "field": 2356 + }, + { + "right": false, + "state": "Kansas", + "pc": 43405, + "field": 3204 + } + ], + "exit": { + "disk_writes": 0, + "disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "machine_frame": 1868, + "frame_number": 1868, + "image_content": true, + "cpu": "6809", + "cycles": 38991590, + "generation": 2, + "revision": 0, + "remaining_field_budget": 214132, + "field_clock": 1868, + "isolated": true, + "state": "running", + "ram_kb": 512, + "screen_text": "DISK EXTENDED COLOR BASIC 2.1\nCOPR. 1982, 1986 BY TANDY\nUNDER LICENSE FROM MICROSOFT\nAND MICROWARE SYSTEMS CORP.\n\nOK\nDOS\nLOADM\"CAPITAL.BIN\":EXEC\nTHANKS FOR PLAYING CAPITAL QUEST\n!\nOK\n", + "project_id": "B89E5EEE-4062-45A7-96F4-4599980CEBAA", + "boot": 1, + "artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "remaining_boots": 15, + "width": 640, + "run_id": "803E3205-EE55-4E9D-BC15-E91FDE83C2A6", + "height": 480, + "pc": 42963, + "disk_reads": 24576, + "disk_provenance": { + "artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "origin_artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "origin_artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "origin": "verified_artifact" + }, + "disk_dirty": false, + "disk_origin": "verified_artifact", + "fields": 1868, + "disk_original_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f" + }, + "retained": [ + { + "disk_original_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "disk_retained": true, + "machine_frame": 3864, + "status": "stopped", + "disk_provenance": { + "origin_artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "origin_artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "origin": "verified_artifact" + }, + "retained_disk": { + "origin": "verified_artifact", + "run_id": "A9D3E454-0015-403E-A70C-D191A6143633", + "disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "created_at": "2026-11-10T02:17:38Z", + "byte_count": 161280, + "origin_artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "origin_artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "retained_disk_id": "A9D3E454-0015-403E-A70C-D191A6143633" + }, + "cpu": "6809", + "cycles": 102568418, + "generation": 2, + "retained_disk_id": "A9D3E454-0015-403E-A70C-D191A6143633", + "revision": 0, + "request_id": "bc96850e-e40f-4330-82f6-3a8c66a53fe3", + "remaining_field_budget": 212136, + "field_clock": 3864, + "isolated": true, + "state": "paused", + "ram_kb": 512, + "project_id": "B89E5EEE-4062-45A7-96F4-4599980CEBAA", + "boot": 1, + "artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "remaining_boots": 15, + "artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "run_id": "A9D3E454-0015-403E-A70C-D191A6143633", + "pc": 11386, + "disk_reads": 24576, + "fields": 3864, + "disk_origin": "verified_artifact", + "disk_dirty": false, + "disk_writes": 0, + "retained_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f" + }, + { + "fields": 1868, + "disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "machine_frame": 1868, + "disk_retained": true, + "status": "stopped", + "disk_original_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "cpu": "6809", + "retained_disk": { + "origin": "verified_artifact", + "origin_artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "origin_artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "created_at": "2026-11-10T02:17:40Z", + "run_id": "803E3205-EE55-4E9D-BC15-E91FDE83C2A6", + "byte_count": 161280, + "retained_disk_id": "803E3205-EE55-4E9D-BC15-E91FDE83C2A6" + }, + "retained_disk_id": "803E3205-EE55-4E9D-BC15-E91FDE83C2A6", + "generation": 2, + "revision": 0, + "cycles": 38991590, + "request_id": "a768e0d8-9980-45be-a10a-512f65ea0e88", + "remaining_field_budget": 214132, + "field_clock": 1868, + "isolated": true, + "state": "paused", + "ram_kb": 512, + "project_id": "B89E5EEE-4062-45A7-96F4-4599980CEBAA", + "boot": 1, + "artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "remaining_boots": 15, + "run_id": "803E3205-EE55-4E9D-BC15-E91FDE83C2A6", + "pc": 42963, + "disk_reads": 24576, + "disk_provenance": { + "artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "origin_artifact_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f", + "origin_artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "artifact_id": "55C22401-B69A-40A4-9C04-C00281007402", + "origin": "verified_artifact" + }, + "disk_writes": 0, + "disk_dirty": false, + "disk_origin": "verified_artifact", + "retained_disk_sha256": "d9464356aadaa53b2f8e74aa7b50ba8f96f900950747408ddfa077a2867c3b4f" + } + ], + "audio_recording_available": false +} \ No newline at end of file diff --git a/docs/evidence/feedback-typed-report.json b/docs/evidence/feedback-typed-report.json new file mode 100644 index 0000000..5cea53c --- /dev/null +++ b/docs/evidence/feedback-typed-report.json @@ -0,0 +1,395 @@ +{ + "score": 47, + "corrections": 2, + "questions": [ + { + "question": 1, + "code": "MN", + "answer": "sT pAuL", + "correct": true, + "correction": false + }, + { + "question": 2, + "code": "WV", + "answer": "Chalreston", + "correct": true, + "correction": true + }, + { + "question": 3, + "code": "CT", + "answer": "Austin", + "correct": false, + "correction": false + }, + { + "question": 4, + "code": "KY", + "answer": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "correct": false, + "correction": false + }, + { + "question": 5, + "code": "FL", + "answer": "Tallhassee", + "correct": false, + "correction": false + }, + { + "question": 6, + "code": "LA", + "answer": " bAtOn rOuGe ", + "correct": true, + "correction": false + }, + { + "question": 7, + "code": "WY", + "answer": "cheyenne", + "correct": true, + "correction": false + }, + { + "question": 8, + "code": "OK", + "answer": "OKLAHOMA CITY", + "correct": true, + "correction": false + }, + { + "question": 9, + "code": "MT", + "answer": "HeLeNa", + "correct": true, + "correction": false + }, + { + "question": 10, + "code": "TX", + "answer": "austin", + "correct": true, + "correction": false + }, + { + "question": 11, + "code": "GA", + "answer": "ATLANTA", + "correct": true, + "correction": false + }, + { + "question": 12, + "code": "SC", + "answer": "CoLuMbIa", + "correct": true, + "correction": false + }, + { + "question": 13, + "code": "NH", + "answer": "concord", + "correct": true, + "correction": false + }, + { + "question": 14, + "code": "UT", + "answer": "SALT LAKE CITY", + "correct": true, + "correction": false + }, + { + "question": 15, + "code": "VA", + "answer": "RiChMoNd", + "correct": true, + "correction": false + }, + { + "question": 16, + "code": "NY", + "answer": "albany", + "correct": true, + "correction": false + }, + { + "question": 17, + "code": "IL", + "answer": "SPRINGFIELD", + "correct": true, + "correction": false + }, + { + "question": 18, + "code": "NV", + "answer": "CaRsOn cItY", + "correct": true, + "correction": false + }, + { + "question": 19, + "code": "RI", + "answer": "providence", + "correct": true, + "correction": false + }, + { + "question": 20, + "code": "IN", + "answer": "INDIANAPOLIS", + "correct": true, + "correction": false + }, + { + "question": 21, + "code": "MA", + "answer": "BoStOn", + "correct": true, + "correction": false + }, + { + "question": 22, + "code": "HI", + "answer": "honolulu", + "correct": true, + "correction": false + }, + { + "question": 23, + "code": "ME", + "answer": "AUGUSTA", + "correct": true, + "correction": false + }, + { + "question": 24, + "code": "VT", + "answer": "MoNtPeLiEr", + "correct": true, + "correction": false + }, + { + "question": 25, + "code": "CO", + "answer": "Dnever", + "correct": true, + "correction": true + }, + { + "question": 26, + "code": "AL", + "answer": "MONTGOMERY", + "correct": true, + "correction": false + }, + { + "question": 27, + "code": "WI", + "answer": "MaDiSoN", + "correct": true, + "correction": false + }, + { + "question": 28, + "code": "AK", + "answer": "juneau", + "correct": true, + "correction": false + }, + { + "question": 29, + "code": "OH", + "answer": "COLUMBUS", + "correct": true, + "correction": false + }, + { + "question": 30, + "code": "MD", + "answer": "AnNaPoLiS", + "correct": true, + "correction": false + }, + { + "question": 31, + "code": "MO", + "answer": "jefferson city", + "correct": true, + "correction": false + }, + { + "question": 32, + "code": "PA", + "answer": "HARRISBURG", + "correct": true, + "correction": false + }, + { + "question": 33, + "code": "MS", + "answer": "JaCkSoN", + "correct": true, + "correction": false + }, + { + "question": 34, + "code": "TN", + "answer": "nashville", + "correct": true, + "correction": false + }, + { + "question": 35, + "code": "KS", + "answer": "TOPEKA", + "correct": true, + "correction": false + }, + { + "question": 36, + "code": "NE", + "answer": "LiNcOlN", + "correct": true, + "correction": false + }, + { + "question": 37, + "code": "WA", + "answer": "olympia", + "correct": true, + "correction": false + }, + { + "question": 38, + "code": "NC", + "answer": "RALEIGH", + "correct": true, + "correction": false + }, + { + "question": 39, + "code": "SD", + "answer": "PiErRe", + "correct": true, + "correction": false + }, + { + "question": 40, + "code": "OR", + "answer": "salem", + "correct": true, + "correction": false + }, + { + "question": 41, + "code": "DE", + "answer": "DOVER", + "correct": true, + "correction": false + }, + { + "question": 42, + "code": "NM", + "answer": "SaNtA Fe", + "correct": true, + "correction": false + }, + { + "question": 43, + "code": "NJ", + "answer": "trenton", + "correct": true, + "correction": false + }, + { + "question": 44, + "code": "ID", + "answer": "BOISE", + "correct": true, + "correction": false + }, + { + "question": 45, + "code": "IA", + "answer": "DeS MoInEs", + "correct": true, + "correction": false + }, + { + "question": 46, + "code": "ND", + "answer": "bismarck", + "correct": true, + "correction": false + }, + { + "question": 47, + "code": "MI", + "answer": "LANSING", + "correct": true, + "correction": false + }, + { + "question": 48, + "code": "AR", + "answer": "LiTtLe rOcK", + "correct": true, + "correction": false + }, + { + "question": 49, + "code": "AZ", + "answer": "phoenix", + "correct": true, + "correction": false + }, + { + "question": 50, + "code": "CA", + "answer": "SACRAMENTO", + "correct": true, + "correction": false + } + ], + "run_id": "D42EB64B-105D-4733-B659-C87DD2F60198", + "exit": { + "disk_writes": 0, + "disk_sha256": "e4a69fd03faa7114f2ccac58262db2ad6fd2e9e656334d6304d52322065ccdf0", + "machine_frame": 123644, + "frame_number": 123644, + "image_content": true, + "cpu": "6809", + "cycles": 3674728796, + "revision": 0, + "generation": 2, + "remaining_field_budget": 92356, + "field_clock": 123644, + "isolated": true, + "state": "running", + "ram_kb": 512, + "screen_text": "DISK EXTENDED COLOR BASIC 2.1\nCOPR. 1982, 1986 BY TANDY\nUNDER LICENSE FROM MICROSOFT\nAND MICROWARE SYSTEMS CORP.\n\nOK\nDOS\nLOADM\"CAPITAL.BIN\":EXEC\nTHANKS FOR PLAYING CAPITAL QUEST\n!\nOK\n", + "project_id": "B89E5EEE-4062-45A7-96F4-4599980CEBAA", + "boot": 1, + "artifact_disk_sha256": "e4a69fd03faa7114f2ccac58262db2ad6fd2e9e656334d6304d52322065ccdf0", + "remaining_boots": 15, + "height": 480, + "width": 640, + "run_id": "D42EB64B-105D-4733-B659-C87DD2F60198", + "artifact_id": "C4532AF8-BF4F-4401-9ADC-DDC62D90AC0F", + "pc": 42963, + "disk_reads": 24576, + "disk_dirty": false, + "disk_provenance": { + "artifact_disk_sha256": "e4a69fd03faa7114f2ccac58262db2ad6fd2e9e656334d6304d52322065ccdf0", + "origin_artifact_disk_sha256": "e4a69fd03faa7114f2ccac58262db2ad6fd2e9e656334d6304d52322065ccdf0", + "origin_artifact_id": "C4532AF8-BF4F-4401-9ADC-DDC62D90AC0F", + "artifact_id": "C4532AF8-BF4F-4401-9ADC-DDC62D90AC0F", + "origin": "verified_artifact" + }, + "fields": 123644, + "disk_origin": "verified_artifact", + "disk_original_sha256": "e4a69fd03faa7114f2ccac58262db2ad6fd2e9e656334d6304d52322065ccdf0" + } +} \ No newline at end of file diff --git a/main.c b/main.c index 87c89af..4a0d634 100644 --- a/main.c +++ b/main.c @@ -49,7 +49,7 @@ static U8 title(void) text(8,149,"Choice: 1-4. Type: letters, spaces, Enter.",7); text(8,160,"Backspace edits. Near spelling: retry/reveal.",2); text(8,171,"50 questions. Release keys between presses.",2); - text(8,182,"Gold marks the state. SPACE after feedback.",6); + text(8,182,"Choice: auto next. Typed: SPACE to continue.",6); present();c=choose("12CQ");if(c=='C')credits(); }while(c=='C'); return c; @@ -121,12 +121,24 @@ static U8 typed_answer(void) } } } +static void answer_sound(U8 right) +{ + /* Color BASIC SOUND uses built-in audio and normal-speed timing. + Keep the graphics page visible while playing a rising or falling pair. */ + setHighSpeed(FALSE); + if(right) {sound(170,2);sound(210,3);} + else {sound(100,3);sound(60,4);} + setHighSpeed(TRUE); +} static void feedback(U8 right) { question_screen();phase=3; text(8,158,right?"CORRECT!":"NOT THIS TIME.",right?6:5); sprintf(line,"The capital is %s.",states[current_state].capital);text(8,170,line,7); - text(8,183,"Release your key, then SPACE to continue.",2);present();choose(" "); + text(8,183,mode==1?"Next question follows automatically.":"Release your key, then SPACE to continue.",2); + present();answer_sound(right); + if(mode==1) delay(90); /* 1.5 seconds to read the answer after the tone. */ + else choose(" "); } static U8 results(void) { diff --git a/include/map_data.h b/map_data.h similarity index 100% rename from include/map_data.h rename to map_data.h diff --git a/include/quiz.h b/quiz.h similarity index 100% rename from include/quiz.h rename to quiz.h diff --git a/tests/playtest_mc.py b/tests/playtest_mc.py index 889782a..b6307cd 100644 --- a/tests/playtest_mc.py +++ b/tests/playtest_mc.py @@ -22,13 +22,25 @@ for q,state in enumerate(order): assert gold>=len(points)*.8,(q,rows[state][0],gold,len(points)) right=q%7!=0;selection=correctpos if right else (correctpos+1)%4 if right:score+=1 - # Hold the first answer through feedback: it must not advance to question 2. - c['key'](run,str(selection+1),600 if q==0 else 8,450) - feedback=c['capture'](run,name+'-feedback');fs=Screen(str(EVIDENCE)+'/'+name+'-feedback.png') + # Read the feedback as soon as it appears, before its automatic timeout. + held=[str(selection+1)] if q==0 else [] + c['inp'](run,[dict(keys=[str(selection+1)],fields=8),dict(keys=held,fields=80)]) + for attempt in range(35): + feedback=c['capture'](run,name+'-feedback');fs=Screen(str(EVIDENCE)+'/'+name+'-feedback.png') + if fs.text(8,158,24) in ('CORRECT!','NOT THIS TIME.'):break + c['inp'](run,[dict(keys=held,fields=20)]) assert fs.text(8,158,24)==('CORRECT!' if right else 'NOT THIS TIME.'),(q,fs.text(8,158,24)) assert fs.text(8,170,50)==f'The capital is {rows[state][2]}.',(q,fs.text(8,170,50)) + assert fs.text(8,183,48)=='Next question follows automatically.' evidence.append(dict(question=q+1,code=rows[state][0],state=rows[state][1],options=opts,answer=opts[selection],correct=right,score=score,gold_pixels=gold,expected_state_pixels=len(points),field=meta['field_clock'])) - c['key'](run,'space',8,500) + # No Space/Enter/answer input advances feedback: elapsed guest fields do it. + c['inp'](run,[dict(keys=held,fields=600)]) + if q==0: + c['inp'](run,[dict(keys=held,fields=600)]) + c['capture'](run,'held-key-next-question');hs=Screen(str(EVIDENCE)+'/held-key-next-question.png') + assert hs.text(8,19,45)==f'Question 2 of 50 Score {score}' + assert hs.text(8,183,48)=='Press 1, 2, 3 or 4' + c['inp'](run,[dict(keys=[],fields=8)]) print(q+1,rows[state][0],score,flush=True) result=c['capture'](run,'mc-results');s=Screen(str(EVIDENCE)+'/mc-results.png') assert s.text(8,48,45)==f'{score} / 50 correct {score*2}%',s.text(8,48,45) @@ -49,5 +61,5 @@ for page in range(3): c['key'](run,'b',8,500);c['key'](run,'p',8,500);c['capture'](run,'replay-title');c['key'](run,'q',8,200);final=c['capture'](run,'mc-exit') assert 'screen_text' in final or final.get('screen_text_unavailable') is None,final json.dump(dict(score=score,positions=pos,questions=evidence,run_id=run,artifact=result['artifact_id'],exit=final),open(str(EVIDENCE)+'/mc-report.json','w'),indent=2) -print('PASS complete multiple-choice quiz, all 50 masks, 42/50, review, held-key feedback, replay, exit.',flush=True) +print('PASS complete multiple-choice quiz, all 50 masks, automatic feedback advance without Space, held-key protection, 42/50, review, replay, exit.',flush=True) c['v'].close() diff --git a/tests/playtest_typed.py b/tests/playtest_typed.py index c4d8736..cf004ce 100644 --- a/tests/playtest_typed.py +++ b/tests/playtest_typed.py @@ -25,6 +25,9 @@ settle();c['key'](run,'2',8,600);settle();c['inp'](run,[dict(keys=['shift','0'], type_text('sT pAuL');s=cap('typed-alias-input');print('input=',s.text(8,158,45),flush=True) assert s.text(8,158,45)=='sT pAuL_',s.text(8,158,45) press('enter',8,600);s=cap('typed-alias-feedback');assert s.text(8,158,30)=='CORRECT!',s.text(8,158,30) +c['inp'](run,[dict(keys=[],fields=300)]);s=cap('typed-feedback-waits') +assert s.text(8,19,45)=='Question 1 of 50 Score 1' +assert s.text(8,183,48)=='Release your key, then SPACE to continue.' score=1;report.append(dict(question=1,code='MN',answer='sT pAuL',correct=True,correction=False));c['key'](run,'space',8,600);settle() for q in range(1,50): st=order[q];code,name,capital=rows[st];s=cap(f'typed-q{q+1:02d}-{code}') diff --git a/tools/prepare_assets.py b/tools/prepare_assets.py index ca39078..464f60e 100644 --- a/tools/prepare_assets.py +++ b/tools/prepare_assets.py @@ -146,7 +146,7 @@ def main(): png(ROOT/'assets'/('preview-'+name+'.png'),w,h,pix) assert all(meta['national']['pixels'].values()),meta['national']['pixels'] (ROOT/'src/map_data.c').write_text('/* Adapted from Fla-shop.com, CC BY 4.0. See assets/CREDITS.md. */\n#include "map_data.h"\n'+''.join(arrays)) - (ROOT/'include/map_data.h').write_text('\n'.join('extern const unsigned char '+n+'_spans[];\nextern const unsigned '+n+'_offsets[51];' for n,*_ in views)+'\n') + (ROOT/'map_data.h').write_text('\n'.join('extern const unsigned char '+n+'_spans[];\nextern const unsigned '+n+'_offsets[51];' for n,*_ in views)+'\n') (ROOT/'src/states.c').write_text('#include "quiz.h"\nconst State states[50] = {\n'+',\n'.join('{"%s","%s","%s"}'%tuple(r) for r in rows)+'\n};\n') meta['source_component_pixels']=counts (ROOT/'data/map-manifest.json').write_text(json.dumps(meta,indent=2)+'\n') diff --git a/include/ui.h b/ui.h similarity index 100% rename from include/ui.h rename to ui.h