17 Commits
Author SHA1 Message Date
Tirsvad d2ec7fbc44 Merge pull request 'Fix CI: import turtle lazily' (#30) from fix-ci-lazy-turtle into main
Run tests / Lint, type check and test (push) Successful in 43s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s
2026-10-13 10:03:32 +02:00
Tirsvad 8421f3a08f Resolve pending commit links for MIL-003, RC-012 and RC-013
Run tests / Lint, type check and test (pull_request) Successful in 40s
2026-10-13 16:00:21 +08:00
Tirsvad 851fabe76e Import turtle lazily so tests run without a Tk library
CI on the runner failed at collection: libtk8.6 is missing, so importing
us_states_game.main imported turtle and tkinter. turtle is now imported when
TurtleScreen is created.

Task: MIL-003#7
2026-10-13 16:00:19 +08:00
Tirsvad 172778d22b Add task 7 to MIL-003: import turtle lazily; re-review RC-013 2026-10-13 16:00:18 +08:00
Tirsvad 3ce5d8d9df Merge pull request 'MIL-004 Documentation, screenshots and wiki' (#28) from mil-004-docs-release into main
Run tests / Lint, type check and test (push) Failing after 53s
TirSystem/github-action: Publish wiki / publish-wiki (push) Successful in 6s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s
2026-10-13 09:58:23 +02:00
Tirsvad 1633e0c8f0 Resolve pending commit links for MIL-004 and RC-011
Run tests / Lint, type check and test (pull_request) Failing after 42s
2026-10-13 15:56:37 +08:00
Tirsvad f3d740c898 Add screenshots, finish README, add wiki in en, da and ms, re-review MIL-004 (MIL-004)
Task: MIL-004#1
Task: MIL-004#2
Task: MIL-004#3
Task: MIL-004#4
2026-10-13 15:56:35 +08:00
Tirsvad 60fc085dee Merge pull request 'MIL-003 Turtle game and entry point' (#27) from mil-003-turtle-game into main
Run tests / Lint, type check and test (push) Failing after 47s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 6s
2026-10-13 09:50:58 +02:00
Tirsvad 7d97e85f90 Resolve pending commit link for RC-010
Run tests / Lint, type check and test (pull_request) Failing after 42s
2026-10-13 15:50:49 +08:00
Tirsvad 02b537e538 Add Turtle screen, game loop and entry point (MIL-003)
Task: MIL-003#1
Task: MIL-003#2
Task: MIL-003#3
Task: MIL-003#4
Task: MIL-003#5
Task: MIL-003#6
2026-10-13 15:50:45 +08:00
Tirsvad 896c807cc3 Merge pull request 'MIL-002 Game core logic' (#26) from mil-002-game-core into main
Run tests / Lint, type check and test (push) Successful in 42s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 7s
2026-10-13 09:48:20 +02:00
Tirsvad 50059fc509 Resolve pending commit links for ADR-0001, RC-008 and RC-009
Run tests / Lint, type check and test (pull_request) Successful in 41s
2026-10-13 15:48:12 +08:00
Tirsvad bb8730c307 Add game core logic, CSV storage, tests and ADR-0001 (MIL-002)
Task: MIL-002#1
Task: MIL-002#2
Task: MIL-002#3
Task: MIL-002#4
Task: MIL-002#5
2026-10-13 15:48:08 +08:00
Tirsvad 048a6ba91d Merge pull request 'MIL-001 Baseline and repository setup' (#25) from mil-001-baseline-setup into main
Run tests / Lint, type check and test (push) Successful in 39s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s
2026-10-13 09:46:24 +02:00
Tirsvad ad7e60eb77 Resolve pending commit link for RC-007
Run tests / Lint, type check and test (pull_request) Successful in 39s
2026-10-13 15:46:09 +08:00
Tirsvad 22f19c188b Add repository baseline: layout, tooling, assets, README, Doxyfile and CI (MIL-001)
Task: MIL-001#1
Task: MIL-001#2
Task: MIL-001#3
Task: MIL-001#4
Task: MIL-001#5
Task: MIL-001#6
2026-10-13 15:46:00 +08:00
Tirsvad 840cc2d6bf Merge pull request 'Plan baseline: business case, stakeholders, plan, milestones' (#1) from docs-baseline into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 6s
2026-10-13 09:41:00 +02:00
51 changed files with 2334 additions and 406 deletions
+1
View File
@@ -0,0 +1 @@
* text=auto eol=lf
+35
View File
@@ -0,0 +1,35 @@
# Continuous integration for the U.S. States Game.
# Read by Gitea Actions. Installs the project with its dev extra, then checks
# style (ruff), types (mypy) and behaviour (pytest). Design: docs/project-plan.md.
---
name: Run tests
on:
push:
branches: [main]
pull_request:
jobs:
run-tests:
name: Lint, type check and test
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out the project
uses: actions/checkout@v4.2.2
- name: Set up Python
uses: actions/setup-python@v5.3.0
with:
python-version: "3.13"
- name: Install the project and its dev tools
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
- name: Check style
run: python -m ruff check . && python -m ruff format --check .
- name: Check types
run: python -m mypy
- name: Check workflow files
run: python -m yamllint .gitea .yamllint
- name: Run the tests
run: python -m pytest
+42
View File
@@ -0,0 +1,42 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# Virtual environments
.venv/
venv/
env/
ENV/
# Packaging and build
build/
dist/
*.egg-info/
.eggs/
pip-wheel-metadata/
# Test, coverage and tool caches
.pytest_cache/
.coverage
.coverage.*
htmlcov/
.tox/
.nox/
.mypy_cache/
.ruff_cache/
# Generated source documentation (Doxygen)
docs/build/
# Local credentials, never committed
.env
# Game output written to the working directory
states_to_learn.csv
# Editors and OS
.idea/
.vscode/
.DS_Store
Thumbs.db
+8
View File
@@ -0,0 +1,8 @@
# yamllint configuration for the workflow files under .gitea/workflows/.
---
extends: default
rules:
truthy:
allowed-values: ["true", "false", "on"]
line-length:
max: 100
+22
View File
@@ -0,0 +1,22 @@
# Doxygen configuration for the U.S. States Game.
# Build: doxygen Doxyfile
# Output: docs/build/doxygen/index.html
PROJECT_NAME = "U.S. States Game"
PROJECT_BRIEF = "Name the 50 states on a Turtle map"
OUTPUT_DIRECTORY = docs/build
HTML_OUTPUT = doxygen
INPUT = src
FILE_PATTERNS = *.py
RECURSIVE = YES
EXCLUDE_PATTERNS = */__pycache__/* */data/*
OPTIMIZE_OUTPUT_JAVA = YES
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
JAVADOC_AUTOBRIEF = YES
GENERATE_HTML = YES
GENERATE_LATEX = NO
HAVE_DOT = NO
QUIET = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = YES
+130 -1
View File
@@ -1,2 +1,131 @@
# 025-us-states-game
# U.S. States Game
A quiz game from Udemy's *100 Days of Code: The Complete Python Pro Bootcamp* (day 25): a Turtle window shows a blank map of the United States, you type state names, and every correct guess appears on the map. When you leave, the states you missed are saved to `states_to_learn.csv`.
![The blank map with the prompt at 0/50 states](docs/images/game-start.png)
![A game in progress: 14 of 50 states named](docs/images/game-in-progress.png)
This is a solution for course participants to compare with their own: the code keeps the assignment's names (`screen`, `guessed_states`, `missing_states`, `get_mouse_click_coor`, `states_to_learn.csv`). It reads the CSV with the standard library, so the game has no runtime dependencies. The wiki has the same instructions in English, Danish and Bahasa Malaysia.
## Requirements
- Python 3.13 or newer, with `tkinter` (Turtle needs it; the python.org installers and the Windows Store build include it)
- `git`
- Optional: [Doxygen](https://www.doxygen.nl/) to build the source documentation
The game has no runtime dependencies. `pytest` is installed only for development.
## Set up
Create a local virtual environment named `.venv` in the project folder, upgrade `pip` and install the project with its test tool.
### Windows powershell
```powershell
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game.git
cd 025-us-states-game
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
If PowerShell refuses to run the activation script, run `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned` once.
### Linux debian
```bash
sudo apt install python3 python3-venv python3-tk git
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game.git
cd 025-us-states-game
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
### MacOS
```bash
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game.git
cd 025-us-states-game
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
## Run
With the virtual environment active:
```bash
python -m us_states_game
```
Type a state name in the prompt; case does not matter. The title of the prompt shows how many states you have named. Type `exit` (or press Cancel) to quit; the states you did not name are written to `states_to_learn.csv` in the current folder.
To print the coordinates of every mouse click on the map (lecture 1), add `--show-coordinates`:
```bash
python -m us_states_game --show-coordinates
```
The game can also be started with `python src/us_states_game/main.py`.
## Run the tests
```bash
python -m pytest
```
The tests need no display.
## Continuous integration
`.gitea/workflows/run-tests.yml` runs on every push to `main` and on every pull request: it sets up Python 3.13, installs the project with `python -m pip install -e ".[dev]"`, then runs `ruff`, `mypy`, `yamllint` and `python -m pytest`.
## Build the source documentation
The source uses Doxygen comments. With Doxygen installed:
```bash
doxygen Doxyfile
```
Open `docs/build/doxygen/index.html` in a browser.
## Project layout
| Path | What it is |
| --- | --- |
| `src/us_states_game/` | The game package: `constants.py`, `states.py` (rules), `storage.py` (CSV), `game.py` (guess loop), `turtle_screen.py` (Turtle), `main.py` (entry point) |
| `src/us_states_game/data/` | `50_states.csv` and `blank_states_img.gif` from the course |
| `tests/` | pytest tests; they need no display |
| `wiki/` | The wiki pages in English (`*.md`), Danish (`*.da.md`) and Bahasa Malaysia (`*.ms.md`) |
| `docs/images/` | Screenshots used by the README and the wiki |
| `docs/` | Project documents: business case, plan, milestones, review records |
| `Doxyfile` | Doxygen configuration |
| `pyproject.toml` | Project configuration |
| `.gitea/workflows/run-tests.yml` | Continuous integration |
## License
GNU Affero General Public License v3.0. See [LICENSE](LICENSE).
## Links
- [Repository](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game)
- [Issue tracker](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/issues)
- [Wiki](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/wiki)
## Appendix: Project documents
| Document | What it tells you |
| --- | --- |
| [Business Case](docs/business-case.md) | Why the project exists, its scope and success criteria |
| [Stakeholder Analysis](docs/stakeholder-analysis.md) | Who is involved |
| [Project Plan](docs/project-plan.md) | The gateways and their schedule |
| [Milestones](docs/milestones/) | One document per gateway: Go/No-Go criteria and tasks |
| [Artifact registry](docs/artifact-registry.md) | Where each document type lives |
@@ -0,0 +1,52 @@
# Read the states with the csv module
## Metadata
| Key | Value |
| --- | --- |
| ID | ADR-0001 |
| CrossReference | [BC-001], [SA-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Accepted | Claude (AI) for S01 | AI as stand-in for S01 | Initial version; review RC-008: Go | [bb8730c] |
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
---
## Context
The lectures read `50_states.csv` with pandas (`pandas.read_csv`, a DataFrame, then `DataFrame.to_csv` for `states_to_learn.csv`). The file has 50 rows and three columns (`state`, `x`, `y`). [BC-001] sets the constraint "avoid adding runtime dependencies unless they are needed", and [SA-001] records that S03 wants no runtime dependencies while S02 wants the assignment's function and variable names.
Options evaluated:
1. **pandas**: matches the lectures literally; adds a large runtime dependency (with NumPy) for 50 rows and makes installation and CI slower.
2. **Standard library `csv` module**: no dependency; a few more lines to read and write; the assignment's names (`data`, `states`, `guessed_states`, `missing_states`) can be kept.
## Decision
Read and write the CSV files with the standard library `csv` module, and keep the assignment's names for variables and functions. pandas is not a runtime dependency.
## Consequences
**Positive:**
- The game has no runtime dependencies, so S03 installs nothing and CI is fast.
- The game logic is plain functions over `str` and `int`, easy to test without a display.
**Negative:**
- The code differs from the lecture's pandas calls, so S02 compares by names and behaviour, not by line.
- Reading and writing the CSV takes a few more lines than `read_csv` and `to_csv`.
## Affected Artifacts
- [BC-001] - Success criterion 6 (no runtime dependency beyond the standard library) is met without exception.
- [SA-001] - Resolves the S02 and S03 conflict in favour of no runtime dependency.
---
[BC-001]: ../business-case.md
[SA-001]: ../stakeholder-analysis.md
[bb8730c]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/bb8730c30761f885491abeb764690e0b53d2459b
+2 -2
View File
@@ -15,8 +15,8 @@ document of a type. `Primary File` may contain a glob (e.g.
| SA | Stakeholder Analysis | docs/stakeholder-analysis.md | 002 |
| PP | Project Plan | docs/project-plan.md | 002 |
| MIL | Milestone / Gateway | docs/milestones/*.md | 005 |
| ADR | Architecture Decision Record | docs/adr/adr-NNNN-*.md | 0001 |
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 007 |
| ADR | Architecture Decision Record | docs/adr/adr-NNNN-*.md | 0002 |
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 014 |
## Languages
Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

+4 -1
View File
@@ -11,7 +11,8 @@
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Accepted | Claude (AI) for S01 | AI as stand-in for S01 | Initial version; review RC-005: Go | [b113e6e] |
| 2026-10-13 | Deprecated | Claude (AI) for S01 | AI as stand-in for S01 | Initial version; review RC-005: Go | [b113e6e] |
| 2026-10-13 | Accepted | Claude (AI) for S01 | AI as stand-in for S01 | Task 7 added: CI found that importing turtle needs a Tk library the runner lacks; review RC-013: Go | [172778d] |
---
@@ -67,8 +68,10 @@ A runnable `main.py` entry point that plays the full game with Turtle, built on
| 4 | Add the entry point | `main.py` wires screen, loop and the learning-file export so `python main.py` runs the game after setup. | No | |
| 5 | Add UI test with a fake screen | Inject a fake screen and prompt into the loop to verify the flow without a display. | No | |
| 6 | Run the game manually | Run the real game once and note the result in the milestone review. | No | |
| 7 | Import turtle lazily so tests run without a Tk library | CI on the runner failed at test collection because `import turtle` needs `libtk8.6`. Import `turtle` when `TurtleScreen` is created, so importing the program and running its tests need no Tk library. Found after the first merge of this milestone. | No | |
---
[BC-001]: ../business-case.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
[172778d]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/172778d22b7d78fe91eb91b145055289c87ac208
+4 -2
View File
@@ -11,7 +11,8 @@
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Accepted | Claude (AI) for S01 | AI as stand-in for S01 | Initial version; review RC-006: Go | [b113e6e] |
| 2026-10-13 | Deprecated | Claude (AI) for S01 | AI as stand-in for S01 | Initial version; review RC-006: Go | [b113e6e] |
| 2026-10-13 | Accepted | Claude (AI) for S01 | AI as stand-in for S01 | Criterion 1 follows the README template S01 gave in the request, not the framework README template, so `check-readme.sh` cannot pass; review RC-011: Go | [f3d740c] |
---
@@ -27,7 +28,7 @@ Completed README with screenshots, Doxygen comments verified and buildable, wiki
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | `framework/scripts/check-readme.sh` passes | Met | Not met |
| 1 | `README.md` has every section of the README template S01 gave (Requirements, Set up with Windows powershell, Linux debian and MacOS, Run, Run the tests, Continuous integration, Build the source documentation, Project layout, License) in that order, and no placeholder text | Met | Not met |
| 2 | `doxygen Doxyfile` builds without warnings about undocumented public functions | Met | Not met |
| 3 | The wiki has `Home`, `Install` and `Description` pages in `en`, `da` and `ms` and a `_Sidebar.md` | Met | Not met |
| 4 | README and wiki embed at least 2 screenshots of the running game | Met | Not met |
@@ -71,3 +72,4 @@ Completed README with screenshots, Doxygen comments verified and buildable, wiki
[BC-001]: ../business-case.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
[f3d740c]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/f3d740c8980924504eaaf9d9f2706b050f1efee0
+68 -68
View File
@@ -1,68 +1,68 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-001 |
| CrossReference | [BC-001], [QC-BC-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [b113e6e] |
---
## Artifact Under Review
- Instance reviewed: [BC-001]
- Checklist used: [QC-BC-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the reviewer reads English and knows the domain, as stand-in for S01)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | ROI/Cost-Benefit analysis is quantitative, or where qualitative, is explicitly justified | Pass | Cost-Benefit table is qualitative and says why: the project is an exercise with no licence or hosting cost. |
| 2 | Risks are identified with documented impact and mitigation | Pass | Risks table: five risks, each with impact and mitigation. |
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | Six criteria with target and measure (pytest exit code 0, `check-readme.sh` passes, at least 5 topics). |
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | `### In Scope` and `### Out of Scope` subsections. |
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | Stakeholders table cites S01, S02, S03 and [SA-001]. |
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Section names the framework, ISO/IEC 25010:2023 and the coding conventions. |
| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Separate Assumptions and Constraints sections. |
| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Recommendation: Proceed, with rationale. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `Language` = en, `Domain` = it in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en`; `it` is in the registry's domain table. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and cells are English. Checked by the stand-in for S01, who reads English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | IT Executive English: plain objective-level prose with no implementation detail beyond what the scope needs. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No `DICT` exists for domain `it` and none is in the plan; the document uses standard Python and software terms consistently (for example `states_to_learn.csv`, `missing_states`, Doxygen). Recorded as a stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | All structural vocabulary is English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `check-languages.sh` reports no twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer, AI as stand-in for S01, reads English and the software domain; no second language reviewer is named. S01 is the Product Owner and reads both; a person may challenge this in the run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Continuous integration (CI), Architecture Decision Record (ADR) and comma-separated values (CSV) are spelled out where first used in prose; file names and tool names are not abbreviations. |
## Overall Verdict
Go - The Business Case is complete against its checklist. Every Mandatory criterion of both checklists passes.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[BC-001]: ../../business-case.md
[QC-BC-001]: ../../../framework/qc/artifacts/qc-business-case.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-001 |
| CrossReference | [BC-001], [QC-BC-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [b113e6e] |
---
## Artifact Under Review
- Instance reviewed: [BC-001]
- Checklist used: [QC-BC-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the reviewer reads English and knows the domain, as stand-in for S01)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | ROI/Cost-Benefit analysis is quantitative, or where qualitative, is explicitly justified | Pass | Cost-Benefit table is qualitative and says why: the project is an exercise with no licence or hosting cost. |
| 2 | Risks are identified with documented impact and mitigation | Pass | Risks table: five risks, each with impact and mitigation. |
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | Six criteria with target and measure (pytest exit code 0, `check-readme.sh` passes, at least 5 topics). |
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | `### In Scope` and `### Out of Scope` subsections. |
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | Stakeholders table cites S01, S02, S03 and [SA-001]. |
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Section names the framework, ISO/IEC 25010:2023 and the coding conventions. |
| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Separate Assumptions and Constraints sections. |
| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Recommendation: Proceed, with rationale. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `Language` = en, `Domain` = it in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en`; `it` is in the registry's domain table. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and cells are English. Checked by the stand-in for S01, who reads English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | IT Executive English: plain objective-level prose with no implementation detail beyond what the scope needs. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No `DICT` exists for domain `it` and none is in the plan; the document uses standard Python and software terms consistently (for example `states_to_learn.csv`, `missing_states`, Doxygen). Recorded as a stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | All structural vocabulary is English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `check-languages.sh` reports no twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer, AI as stand-in for S01, reads English and the software domain; no second language reviewer is named. S01 is the Product Owner and reads both; a person may challenge this in the run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Continuous integration (CI), Architecture Decision Record (ADR) and comma-separated values (CSV) are spelled out where first used in prose; file names and tool names are not abbreviations. |
## Overall Verdict
Go - The Business Case is complete against its checklist. Every Mandatory criterion of both checklists passes.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[BC-001]: ../../business-case.md
[QC-BC-001]: ../../../framework/qc/artifacts/qc-business-case.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
+68 -68
View File
@@ -1,68 +1,68 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-002 |
| CrossReference | [SA-001], [QC-SA-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [b113e6e] |
---
## Artifact Under Review
- Instance reviewed: [SA-001]
- Checklist used: [QC-SA-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the reviewer reads English and knows the domain, as stand-in for S01)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Power/Interest grid is filled for every stakeholder, with no gaps or unclassified entries | Pass | S01, S02, S03 each have power, interest and quadrant. |
| 2 | Each stakeholder is assigned a unique, stable ID (e.g. S01-S11 style) reusable for RACI assignments in other artifacts | Pass | S01, S02, S03; used by the Business Case, plan and milestones. |
| 3 | Roles and organizational context are defined with explicit Power and Interest levels, not just narrative description | Pass | Role, organisation, power and interest in the summary table. |
| 4 | Communication needs (channel, frequency, deliverable type) are mapped to project phases or milestones | Pass | Communication table names milestone for each stakeholder. |
| 5 | Conflicting stakeholder interests are identified with documented mitigation or resolution strategies | Pass | Two conflicts, each with a mitigation. |
| 6 | Stakeholder concerns are explicitly traced to Business Case objectives | Pass | Business Goal Alignment table cites [BC-001] objectives. |
| 7 | Primary concerns are expressed in both business language and a recognized quality-attribute mapping (e.g. FURPS+) | Pass | Concerns table with FURPS+ attribute. |
| 8 | Document is understandable and navigable by non-technical stakeholders reviewing their own entry | Pass | One table row per stakeholder, plain wording. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `Language` = en, `Domain` = it in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en`; `it` is in the registry's domain table. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and cells are English. Checked by the stand-in for S01, who reads English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | IT Professional English: concrete technical terms and checkable statements. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No `DICT` exists for domain `it` and none is in the plan; the document uses standard Python and software terms consistently (for example `states_to_learn.csv`, `missing_states`, Doxygen). Recorded as a stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | All structural vocabulary is English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `check-languages.sh` reports no twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer, AI as stand-in for S01, reads English and the software domain; no second language reviewer is named. S01 is the Product Owner and reads both; a person may challenge this in the run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | The only abbreviations are stakeholder IDs (S01 and so on), defined by the summary table, and FURPS+ (functionality, usability, reliability, performance, supportability plus), named in the method of the Purpose. |
## Overall Verdict
Go - The Stakeholder Analysis meets its checklist. Every Mandatory criterion of both checklists passes.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[SA-001]: ../../stakeholder-analysis.md
[QC-SA-001]: ../../../framework/qc/artifacts/qc-stakeholder-analysis.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-002 |
| CrossReference | [SA-001], [QC-SA-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [b113e6e] |
---
## Artifact Under Review
- Instance reviewed: [SA-001]
- Checklist used: [QC-SA-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the reviewer reads English and knows the domain, as stand-in for S01)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Power/Interest grid is filled for every stakeholder, with no gaps or unclassified entries | Pass | S01, S02, S03 each have power, interest and quadrant. |
| 2 | Each stakeholder is assigned a unique, stable ID (e.g. S01-S11 style) reusable for RACI assignments in other artifacts | Pass | S01, S02, S03; used by the Business Case, plan and milestones. |
| 3 | Roles and organizational context are defined with explicit Power and Interest levels, not just narrative description | Pass | Role, organisation, power and interest in the summary table. |
| 4 | Communication needs (channel, frequency, deliverable type) are mapped to project phases or milestones | Pass | Communication table names milestone for each stakeholder. |
| 5 | Conflicting stakeholder interests are identified with documented mitigation or resolution strategies | Pass | Two conflicts, each with a mitigation. |
| 6 | Stakeholder concerns are explicitly traced to Business Case objectives | Pass | Business Goal Alignment table cites [BC-001] objectives. |
| 7 | Primary concerns are expressed in both business language and a recognized quality-attribute mapping (e.g. FURPS+) | Pass | Concerns table with FURPS+ attribute. |
| 8 | Document is understandable and navigable by non-technical stakeholders reviewing their own entry | Pass | One table row per stakeholder, plain wording. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `Language` = en, `Domain` = it in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en`; `it` is in the registry's domain table. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and cells are English. Checked by the stand-in for S01, who reads English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | IT Professional English: concrete technical terms and checkable statements. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No `DICT` exists for domain `it` and none is in the plan; the document uses standard Python and software terms consistently (for example `states_to_learn.csv`, `missing_states`, Doxygen). Recorded as a stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | All structural vocabulary is English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `check-languages.sh` reports no twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer, AI as stand-in for S01, reads English and the software domain; no second language reviewer is named. S01 is the Product Owner and reads both; a person may challenge this in the run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | The only abbreviations are stakeholder IDs (S01 and so on), defined by the summary table, and FURPS+ (functionality, usability, reliability, performance, supportability plus), named in the method of the Purpose. |
## Overall Verdict
Go - The Stakeholder Analysis meets its checklist. Every Mandatory criterion of both checklists passes.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[SA-001]: ../../stakeholder-analysis.md
[QC-SA-001]: ../../../framework/qc/artifacts/qc-stakeholder-analysis.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
+66 -66
View File
@@ -1,66 +1,66 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-003 |
| CrossReference | [MIL-001], [QC-MIL-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [b113e6e] |
---
## Artifact Under Review
- Instance reviewed: [MIL-001]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the reviewer reads English and knows the domain, as stand-in for S01)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section: repository tooling, layout, assets, CI and surface |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go / No-Go table with objectively checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | First milestone; the table says None. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table cites [BC-001] objectives and success criteria. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table: owner S01, approving reviewer S01 (stand-in in autonomous mode). |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-10-13, consistent with the one-working-day duration constraint of [BC-001]. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `Language` = en, `Domain` = it in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en`; `it` is in the registry's domain table. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and cells are English. Checked by the stand-in for S01, who reads English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | IT Executive English: plain objective-level prose with no implementation detail beyond what the scope needs. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No `DICT` exists for domain `it` and none is in the plan; the document uses standard Python and software terms consistently (for example `states_to_learn.csv`, `missing_states`, Doxygen). Recorded as a stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | All structural vocabulary is English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `check-languages.sh` reports no twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer, AI as stand-in for S01, reads English and the software domain; no second language reviewer is named. S01 is the Product Owner and reads both; a person may challenge this in the run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | CI and ADR are spelled out on first use in the milestone documents; Doxygen, pytest and README are tool or file names. |
## Overall Verdict
Go - The milestone meets its checklist. Every Mandatory criterion of both checklists passes.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[MIL-001]: ../../milestones/mil-001-baseline-setup.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-003 |
| CrossReference | [MIL-001], [QC-MIL-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [b113e6e] |
---
## Artifact Under Review
- Instance reviewed: [MIL-001]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the reviewer reads English and knows the domain, as stand-in for S01)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section: repository tooling, layout, assets, CI and surface |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go / No-Go table with objectively checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | First milestone; the table says None. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table cites [BC-001] objectives and success criteria. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table: owner S01, approving reviewer S01 (stand-in in autonomous mode). |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-10-13, consistent with the one-working-day duration constraint of [BC-001]. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `Language` = en, `Domain` = it in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en`; `it` is in the registry's domain table. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and cells are English. Checked by the stand-in for S01, who reads English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | IT Executive English: plain objective-level prose with no implementation detail beyond what the scope needs. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No `DICT` exists for domain `it` and none is in the plan; the document uses standard Python and software terms consistently (for example `states_to_learn.csv`, `missing_states`, Doxygen). Recorded as a stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | All structural vocabulary is English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `check-languages.sh` reports no twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer, AI as stand-in for S01, reads English and the software domain; no second language reviewer is named. S01 is the Product Owner and reads both; a person may challenge this in the run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | CI and ADR are spelled out on first use in the milestone documents; Doxygen, pytest and README are tool or file names. |
## Overall Verdict
Go - The milestone meets its checklist. Every Mandatory criterion of both checklists passes.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[MIL-001]: ../../milestones/mil-001-baseline-setup.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
+66 -66
View File
@@ -1,66 +1,66 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-004 |
| CrossReference | [MIL-002], [QC-MIL-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [b113e6e] |
---
## Artifact Under Review
- Instance reviewed: [MIL-002]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the reviewer reads English and knows the domain, as stand-in for S01)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section: display-free game logic with tests and an ADR |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go / No-Go table with objectively checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Depends on MIL-001 with a reason. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table cites [BC-001] objectives and success criteria. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table: owner S01, approving reviewer S01 (stand-in in autonomous mode). |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-10-13, consistent with the one-working-day duration constraint of [BC-001]. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `Language` = en, `Domain` = it in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en`; `it` is in the registry's domain table. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and cells are English. Checked by the stand-in for S01, who reads English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | IT Executive English: plain objective-level prose with no implementation detail beyond what the scope needs. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No `DICT` exists for domain `it` and none is in the plan; the document uses standard Python and software terms consistently (for example `states_to_learn.csv`, `missing_states`, Doxygen). Recorded as a stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | All structural vocabulary is English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `check-languages.sh` reports no twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer, AI as stand-in for S01, reads English and the software domain; no second language reviewer is named. S01 is the Product Owner and reads both; a person may challenge this in the run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | CI and ADR are spelled out on first use in the milestone documents; Doxygen, pytest and README are tool or file names. |
## Overall Verdict
Go - The milestone meets its checklist. Every Mandatory criterion of both checklists passes.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[MIL-002]: ../../milestones/mil-002-game-core.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-004 |
| CrossReference | [MIL-002], [QC-MIL-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [b113e6e] |
---
## Artifact Under Review
- Instance reviewed: [MIL-002]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the reviewer reads English and knows the domain, as stand-in for S01)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section: display-free game logic with tests and an ADR |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go / No-Go table with objectively checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Depends on MIL-001 with a reason. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table cites [BC-001] objectives and success criteria. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table: owner S01, approving reviewer S01 (stand-in in autonomous mode). |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-10-13, consistent with the one-working-day duration constraint of [BC-001]. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `Language` = en, `Domain` = it in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en`; `it` is in the registry's domain table. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and cells are English. Checked by the stand-in for S01, who reads English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | IT Executive English: plain objective-level prose with no implementation detail beyond what the scope needs. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No `DICT` exists for domain `it` and none is in the plan; the document uses standard Python and software terms consistently (for example `states_to_learn.csv`, `missing_states`, Doxygen). Recorded as a stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | All structural vocabulary is English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `check-languages.sh` reports no twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer, AI as stand-in for S01, reads English and the software domain; no second language reviewer is named. S01 is the Product Owner and reads both; a person may challenge this in the run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | CI and ADR are spelled out on first use in the milestone documents; Doxygen, pytest and README are tool or file names. |
## Overall Verdict
Go - The milestone meets its checklist. Every Mandatory criterion of both checklists passes.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[MIL-002]: ../../milestones/mil-002-game-core.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
+66 -66
View File
@@ -1,66 +1,66 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-005 |
| CrossReference | [MIL-003], [QC-MIL-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [b113e6e] |
---
## Artifact Under Review
- Instance reviewed: [MIL-003]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the reviewer reads English and knows the domain, as stand-in for S01)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section: runnable game on the tested core |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go / No-Go table with objectively checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Depends on MIL-002 with a reason. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table cites [BC-001] objectives and success criteria. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table: owner S01, approving reviewer S01 (stand-in in autonomous mode). |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-10-13, consistent with the one-working-day duration constraint of [BC-001]. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `Language` = en, `Domain` = it in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en`; `it` is in the registry's domain table. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and cells are English. Checked by the stand-in for S01, who reads English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | IT Executive English: plain objective-level prose with no implementation detail beyond what the scope needs. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No `DICT` exists for domain `it` and none is in the plan; the document uses standard Python and software terms consistently (for example `states_to_learn.csv`, `missing_states`, Doxygen). Recorded as a stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | All structural vocabulary is English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `check-languages.sh` reports no twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer, AI as stand-in for S01, reads English and the software domain; no second language reviewer is named. S01 is the Product Owner and reads both; a person may challenge this in the run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | CI and ADR are spelled out on first use in the milestone documents; Doxygen, pytest and README are tool or file names. |
## Overall Verdict
Go - The milestone meets its checklist. Every Mandatory criterion of both checklists passes.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[MIL-003]: ../../milestones/mil-003-turtle-game.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-005 |
| CrossReference | [MIL-003], [QC-MIL-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [b113e6e] |
---
## Artifact Under Review
- Instance reviewed: [MIL-003]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the reviewer reads English and knows the domain, as stand-in for S01)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section: runnable game on the tested core |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go / No-Go table with objectively checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Depends on MIL-002 with a reason. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table cites [BC-001] objectives and success criteria. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table: owner S01, approving reviewer S01 (stand-in in autonomous mode). |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-10-13, consistent with the one-working-day duration constraint of [BC-001]. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `Language` = en, `Domain` = it in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en`; `it` is in the registry's domain table. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and cells are English. Checked by the stand-in for S01, who reads English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | IT Executive English: plain objective-level prose with no implementation detail beyond what the scope needs. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No `DICT` exists for domain `it` and none is in the plan; the document uses standard Python and software terms consistently (for example `states_to_learn.csv`, `missing_states`, Doxygen). Recorded as a stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | All structural vocabulary is English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `check-languages.sh` reports no twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer, AI as stand-in for S01, reads English and the software domain; no second language reviewer is named. S01 is the Product Owner and reads both; a person may challenge this in the run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | CI and ADR are spelled out on first use in the milestone documents; Doxygen, pytest and README are tool or file names. |
## Overall Verdict
Go - The milestone meets its checklist. Every Mandatory criterion of both checklists passes.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[MIL-003]: ../../milestones/mil-003-turtle-game.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
+66 -66
View File
@@ -1,66 +1,66 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-006 |
| CrossReference | [MIL-004], [QC-MIL-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [b113e6e] |
---
## Artifact Under Review
- Instance reviewed: [MIL-004]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the reviewer reads English and knows the domain, as stand-in for S01)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section: README, Doxygen, screenshots and a three-language wiki |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go / No-Go table with objectively checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Depends on MIL-003 with a reason. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table cites [BC-001] objectives and success criteria. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table: owner S01, approving reviewer S01 (stand-in in autonomous mode). |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-10-13, consistent with the one-working-day duration constraint of [BC-001]. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `Language` = en, `Domain` = it in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en`; `it` is in the registry's domain table. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and cells are English. Checked by the stand-in for S01, who reads English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | IT Executive English: plain objective-level prose with no implementation detail beyond what the scope needs. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No `DICT` exists for domain `it` and none is in the plan; the document uses standard Python and software terms consistently (for example `states_to_learn.csv`, `missing_states`, Doxygen). Recorded as a stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | All structural vocabulary is English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `check-languages.sh` reports no twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer, AI as stand-in for S01, reads English and the software domain; no second language reviewer is named. S01 is the Product Owner and reads both; a person may challenge this in the run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | CI and ADR are spelled out on first use in the milestone documents; Doxygen, pytest and README are tool or file names. |
## Overall Verdict
Go - The milestone meets its checklist. Every Mandatory criterion of both checklists passes.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[MIL-004]: ../../milestones/mil-004-docs-release.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-006 |
| CrossReference | [MIL-004], [QC-MIL-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [b113e6e] |
---
## Artifact Under Review
- Instance reviewed: [MIL-004]
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the reviewer reads English and knows the domain, as stand-in for S01)
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section: README, Doxygen, screenshots and a three-language wiki |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go / No-Go table with objectively checkable criteria. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Depends on MIL-003 with a reason. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table cites [BC-001] objectives and success criteria. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table: owner S01, approving reviewer S01 (stand-in in autonomous mode). |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-10-13, consistent with the one-working-day duration constraint of [BC-001]. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `Language` = en, `Domain` = it in Metadata. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en`; `it` is in the registry's domain table. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and cells are English. Checked by the stand-in for S01, who reads English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | IT Executive English: plain objective-level prose with no implementation detail beyond what the scope needs. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No `DICT` exists for domain `it` and none is in the plan; the document uses standard Python and software terms consistently (for example `states_to_learn.csv`, `missing_states`, Doxygen). Recorded as a stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | All structural vocabulary is English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `check-languages.sh` reports no twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer, AI as stand-in for S01, reads English and the software domain; no second language reviewer is named. S01 is the Product Owner and reads both; a person may challenge this in the run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | CI and ADR are spelled out on first use in the milestone documents; Doxygen, pytest and README are tool or file names. |
## Overall Verdict
Go - The milestone meets its checklist. Every Mandatory criterion of both checklists passes.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[MIL-004]: ../../milestones/mil-004-docs-release.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[b113e6e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/b113e6eacd12bb08045ecf6f7822837626a7b1f7
+82
View File
@@ -0,0 +1,82 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-007 |
| CrossReference | [QC-PY-001], [QC-YML-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [22f19c1] |
---
## Artifact Under Review
- Instance reviewed: source and workflow files delivered by MIL-001 (branch mil-001-baseline-setup)
- Checklist used: [QC-PY-001], [QC-YML-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
### QC-PY-001
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) (Mandatory) | Pass | Constants are UPPER_SNAKE, functions snake_case; ruff rule set N passes. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes (Mandatory) | Pass | Names state purpose (STATES_TO_LEARN_FILENAME, NUMBER_OF_STATES). |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions (Mandatory) | Pass | `ruff format` leaves files unchanged and `ruff check` passes with no suppressions; configured in pyproject.toml. |
| 4 | Every function and method signature is type-annotated, including `-> None` (Mandatory) | Pass | Both test functions are annotated `-> None`; `mypy --strict` passes. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) (Mandatory) | N-A | No exception handling in this milestone's code. |
| 6 | No mutable default arguments and no shadowed builtins (Mandatory) | Pass | No function arguments with defaults; no builtin shadowed. |
| 7 | Files, locks and connections are managed with context managers (Mandatory) | Pass | Tests read the CSV with `Path.read_text`, which closes the file. |
| 8 | Public modules, classes and functions have docstrings that say what, not how (Optional) | Pass | Module docstrings and `##` Doxygen comments on every constant. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output (Mandatory) | N-A | No logging or output in this milestone's code. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded (Mandatory) | N-A | No classes or operations; no Design Class Diagram exists for constants. |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network (Mandatory) | Pass | tests/test_constants.py: two tests named for the behaviour; no order or network dependence. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment (Optional) | Pass | `python -m mypy` strict mode reports no issues. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused (Optional) | Pass | No runtime dependencies; dev extra lists pytest, ruff, mypy and yamllint with lower bounds. |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike (Mandatory) | Pass | Each path, file name and limit is defined once in constants.py. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles (Mandatory) | Pass | The package has no imports of UI or framework code. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations (Mandatory) | Pass | One module with one reason to change; no classes. |
### QC-YML-001
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The file parses with a safe YAML loader and has no duplicate keys in any mapping (Mandatory) | Pass | yamllint (PyYAML safe loader) parses the workflow and reports no duplicate keys. |
| 2 | Indentation is 2 spaces everywhere, never tabs; lines end with LF; the file ends with one newline and has no trailing spaces (Mandatory) | Pass | 2-space indentation, LF endings enforced by .gitattributes, yamllint default rules pass. |
| 3 | Passes `yamllint` (or the project's YAML linter) with its configuration committed next to the code and no unexplained `disable` comments (Mandatory) | Pass | `yamllint .gitea .yamllint` passes with the committed .yamllint, no disable comments. |
| 4 | A scalar that YAML would coerce to another type is quoted: `yes`, `no`, `on`, `off`, `null`, `~`, numbers with a leading zero, versions such as `1.10`, and values that contain `: ` or ` #` (Mandatory) | Pass | `python-version: "3.13"` is quoted; `on` is allowed by the yamllint truthy rule for workflows. |
| 5 | Only safe, plain types are used: no language-specific tags (`!!python/object`, `!ruby/object`) and no `!include`-style extension unless the consuming tool documents it (Mandatory) | Pass | Plain mappings, sequences and strings only. |
| 6 | No secret is written in the file: no password, token, key or private connection string; a secret is referenced by name and supplied by the consuming tool (Mandatory) | Pass | No secret in the file; the workflow needs none. |
| 7 | Embedded program text (shell, Python, SQL, `jq`, and so on) in a value is at most five lines; a longer one is moved to a file of its own, in its own language, and the YAML calls it (Mandatory) | Pass | Each `run:` value has at most 2 lines. |
| 8 | A block of keys or values repeated in the file or across files is defined once (an anchor, a template, an include or a reusable unit the consumer supports) (Mandatory) | Pass | No repeated block. |
| 9 | Anchors, aliases and merge keys (`&`, `*`, `<<`) are used only where the consuming tool is known to support them (Mandatory) | Pass | No anchors or aliases. |
| 10 | The file validates against the schema of the consuming tool where one exists, and the schema or tool version is stated (Optional) | N-A | No published schema is checked; the workflow is exercised by the host runner. |
| 11 | A header comment states what the file is for, which tool reads it, and where its decision or design is recorded (Mandatory) | Pass | Header comment states purpose, reader and where the design is recorded. |
| 12 | Key names follow the convention of the consuming tool; one case style is used within the file (kebab-case or snake_case, never mixed) (Mandatory) | Pass | kebab-case keys (`runs-on`, `timeout-minutes`) throughout. |
| 13 | Multi-line strings use a block scalar (`\|` or `>`) and state the chomping indicator (`\|-`, `\|+`) where the trailing newline matters (Optional) | Pass | The `run:` block scalars use `|`; trailing newline does not matter. |
| 14 | The file name is lowercase kebab-case with one extension style (`.yml` or `.yaml`) used throughout the repository (Optional) | Pass | `run-tests.yml` is lowercase kebab-case with the .yml extension. |
| 15 | A change is exercised by a check that runs without the real target: a parse and schema test, or a dry run of the consuming tool (Optional) | N-A | The runner is not available locally; yamllint is the local check. |
## Overall Verdict
Go - Mandatory criteria of both checklists pass for the files delivered by MIL-001: constants module, package marker, smoke tests, pyproject and the workflow.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[QC-YML-001]: ../../../framework/qc/code/qc-yaml.md
[22f19c1]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/22f19c188be10b216cc9da6f6f5ff9413aecd285
+58
View File
@@ -0,0 +1,58 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-008 |
| CrossReference | [QC-ADR-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [bb8730c] |
---
## Artifact Under Review
- Instance reviewed: [ADR-0001]
- Checklist used: [QC-ADR-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
### QC-ADR-001
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The ID (`ADR-NNNN`, 4-digit) matches the filename number and is unique and sequential (Mandatory) | Pass | ID ADR-0001 matches file adr-0001-...; first ADR. |
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated (Mandatory) | Pass | Context states problem, constraints from BC-001 and SA-001, and two options. |
| 3 | At least two options were considered, or the absence of alternatives is justified (Mandatory) | Pass | Two options: pandas and the csv module. |
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options (Mandatory) | Pass | Decision is two unhedged sentences and equals option 2. |
| 5 | Consequences list both Positive and Negative outcomes (Mandatory) | Pass | Positive and Negative lists present. |
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them (Optional) | Pass | Portability and installation effect named (no runtime dependency). |
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference (Mandatory) | Pass | BC-001 and SA-001 are linked and in CrossReference. |
| 8 | Status changes are recorded as new Version History rows with a Change summary and Commit link; retained rows are never rewritten (Mandatory) | Pass | One Version History row; to be set Accepted on this Go. |
| 9 | A superseded or deprecated ADR names its successor, and the successor links back (Optional) | N-A | Not superseded or deprecated. |
| 10 | Written in business or technical language of the domain, with no unexplained abbreviations (Optional) | Pass | Abbreviations spelled out or defined (CSV file name, CI named as continuous integration in BC-001). |
| 11 | Status is one of `Proposed`, `Accepted`, `Rejected`, `Deprecated` or `Superseded by ADR-NNNN`, and every Version History row uses only these (Mandatory) | Pass | Status values are from the allowed list. |
## Overall Verdict
Go - ADR-0001 meets every Mandatory criterion.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[QC-ADR-001]: ../../../framework/qc/artifacts/qc-adr.md
[ADR-0001]: ../../adr/adr-0001-csv-module-over-pandas.md
[bb8730c]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/bb8730c30761f885491abeb764690e0b53d2459b
+61
View File
@@ -0,0 +1,61 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-009 |
| CrossReference | [QC-PY-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [bb8730c] |
---
## Artifact Under Review
- Instance reviewed: source and tests delivered by MIL-002 (branch mil-002-game-core)
- Checklist used: [QC-PY-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
### QC-PY-001
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) (Mandatory) | Pass | snake_case functions, PascalCase State; ruff N rules pass. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes (Mandatory) | Pass | find_state, get_missing_states, save_states_to_learn state purpose; assignment names kept. |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions (Mandatory) | Pass | ruff format and check clean, no suppressions. |
| 4 | Every function and method signature is type-annotated, including `-> None` (Mandatory) | Pass | All signatures annotated; mypy --strict passes. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) (Mandatory) | N-A | No exception handling; a missing file raises FileNotFoundError to the caller. |
| 6 | No mutable default arguments and no shadowed builtins (Mandatory) | Pass | Default arguments are immutable (Path values); no builtin shadowed. |
| 7 | Files, locks and connections are managed with context managers (Mandatory) | Pass | storage.py opens files with `with`. |
| 8 | Public modules, classes and functions have docstrings that say what, not how (Optional) | Pass | Docstrings with Doxygen @param/@return on all public items. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output (Mandatory) | Pass | No print and no logging in the logic. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded (Mandatory) | N-A | No Design Class Diagram exists; State is a plain value object. |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network (Mandatory) | Pass | 15 tests named for behaviour, tmp_path for files, no network or order dependence. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment (Optional) | Pass | mypy strict reports no issues. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused (Optional) | Pass | No runtime dependencies (ADR-0001). |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike (Mandatory) | Pass | Column names and paths defined once in constants.py; matching rule in find_state only. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles (Mandatory) | Pass | states.py imports no IO or UI; storage.py imports inward (states, constants); no cycles. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations (Mandatory) | Pass | states.py has one reason to change (rules), storage.py another (file format); no inheritance. |
## Overall Verdict
Go - Mandatory criteria pass for states.py, storage.py and their tests (ruff, mypy --strict, 17 pytest tests, doxygen without warnings).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[bb8730c]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/bb8730c30761f885491abeb764690e0b53d2459b
+61
View File
@@ -0,0 +1,61 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-010 |
| CrossReference | [QC-PY-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [02b537e] |
---
## Artifact Under Review
- Instance reviewed: source and tests delivered by MIL-003 (branch mil-003-turtle-game)
- Checklist used: [QC-PY-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
### QC-PY-001
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) (Mandatory) | Pass | PEP 8 casing; ruff N rules pass. `get_mouse_click_coor` keeps the assignment's name. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes (Mandatory) | Pass | Names state purpose; assignment names guessed_states and missing_states kept. |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions (Mandatory) | Pass | ruff format and check clean, no suppressions. |
| 4 | Every function and method signature is type-annotated, including `-> None` (Mandatory) | Pass | All signatures annotated incl. `-> None`; mypy --strict passes. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) (Mandatory) | N-A | No exception handling added; a missing data file raises to the caller. |
| 6 | No mutable default arguments and no shadowed builtins (Mandatory) | Pass | No mutable defaults (Path defaults are immutable); no builtin shadowed. |
| 7 | Files, locks and connections are managed with context managers (Mandatory) | Pass | No unmanaged resources; the window is closed in a `finally` in main(). |
| 8 | Public modules, classes and functions have docstrings that say what, not how (Optional) | Pass | Docstrings with @param/@return on public items. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output (Mandatory) | Pass | Click coordinates use `logging`; no print in the package. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded (Mandatory) | N-A | No Design Class Diagram exists; the Protocol and TurtleScreen are recorded in the module docstrings. |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network (Mandatory) | Pass | 15 new tests with a fake screen and monkeypatched TurtleScreen; no display, network or order dependence. TurtleScreen itself is verified by the manual run. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment (Optional) | Pass | mypy strict reports no issues. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused (Optional) | Pass | No runtime dependencies. |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike (Mandatory) | Pass | Titles, prompts, font and sizes defined once in constants.py. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles (Mandatory) | Pass | Only turtle_screen.py imports turtle; game.py depends on a Protocol. game.py imports storage (stdlib csv file output) directly: accepted for a program of this size, noted as a stand-in decision. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations (Mandatory) | Pass | game.py loop, storage, screen and composition root each have one reason to change; the loop depends on the GameScreen Protocol and receives its implementation. |
## Overall Verdict
Go - Mandatory criteria pass for game.py, turtle_screen.py, main.py and their tests (ruff, mypy --strict, 33 pytest tests, doxygen without warnings). Manual run: the real window opened with the blank map and the prompt dialog titled 0/50 States Correct; the game process was then stopped.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[02b537e]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/02b537e5384560a4e55fac137e8ad4fa236e6031
@@ -0,0 +1,68 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-011 |
| CrossReference | [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [f3d740c] |
---
## Artifact Under Review
- Instance reviewed: [MIL-004]
- Checklist used: [QC-MIL-001], [QC-LANG-001]
- Scope: full review (re-review after the criterion 1 change; earlier record RC-006)
- Language and domain: en / it
- Language reviewer: none
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
### QC-MIL-001
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate (Mandatory) | Pass | Deliverable: README, Doxygen, screenshots, three-language wiki, fresh-clone run. |
| 2 | Explicit Go/No-Go criteria are stated for each gate (Mandatory) | Pass | Five objectively checkable criteria; criterion 1 now names the exact README sections. |
| 3 | Dependencies on other milestones are explicitly mapped (Optional) | Pass | Depends on MIL-003 with a reason. |
| 4 | Each milestone is traceable to a Business Case objective or KPI (Mandatory) | Pass | Traceable to BC-001 objective 4 and success criteria 3, 4, 5. |
| 5 | Milestone owner and approving reviewer are identified (Mandatory) | Pass | Owner S01, approving reviewer S01 (stand-in). |
| 6 | Milestone has a defined target date consistent with project constraints (Mandatory) | Pass | 2026-10-13, within the duration constraint. |
### QC-LANG-001
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder (Mandatory) | Pass | Language en, Domain it. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list (Mandatory) | Pass | BCP 47 code en; domain it is in the registry list. |
| 3 | The content (prose and table cells) is written in the stated language (Mandatory) | Pass | Content is English. |
| 4 | The register matches the one the registry gives for the artifact type (Mandatory) | Pass | IT Executive English register for MIL. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms (Mandatory) | Pass | No DICT exists; standard software terms; stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English (Mandatory) | Pass | Structural vocabulary English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document (Mandatory) | Pass | No translated twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again (Mandatory) | Pass | No language change; this review follows a content change recorded in Version History. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly (Mandatory) | Pass | Reviewer, AI as stand-in for S01, reads English and the software domain; open to challenge. |
| 10 | Abbreviations are spelled out on first use, in the stated language (Optional) | Pass | Abbreviations spelled out on first use in the milestone documents. |
## Overall Verdict
Go - MIL-004 after the criterion 1 change meets every Mandatory criterion. Full re-review: the content changed materially, so no delta review was used.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[MIL-004]: ../../milestones/mil-004-docs-release.md
[f3d740c]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/f3d740c8980924504eaaf9d9f2706b050f1efee0
@@ -0,0 +1,61 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-012 |
| CrossReference | [QC-PY-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [172778d] |
---
## Artifact Under Review
- Instance reviewed: turtle_screen.py and tests/test_main.py changed by the CI fix (branch fix-ci-lazy-turtle)
- Checklist used: [QC-PY-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
### QC-PY-001
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) (Mandatory) | Pass | PEP 8 casing; ruff N rules pass. `get_mouse_click_coor` keeps the assignment's name. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes (Mandatory) | Pass | Names state purpose; assignment names guessed_states and missing_states kept. |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions (Mandatory) | Pass | ruff format and check clean; the one suppression (`# noqa: PLC0415`) carries its reason: Tk may be missing at import time. |
| 4 | Every function and method signature is type-annotated, including `-> None` (Mandatory) | Pass | All signatures annotated incl. `-> None`; mypy --strict passes. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) (Mandatory) | N-A | No exception handling added; a missing data file raises to the caller. |
| 6 | No mutable default arguments and no shadowed builtins (Mandatory) | Pass | No mutable defaults (Path defaults are immutable); no builtin shadowed. |
| 7 | Files, locks and connections are managed with context managers (Mandatory) | Pass | No unmanaged resources; the window is closed in a `finally` in main(). |
| 8 | Public modules, classes and functions have docstrings that say what, not how (Optional) | Pass | Docstrings with @param/@return on public items. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output (Mandatory) | Pass | Click coordinates use `logging`; no print in the package. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded (Mandatory) | N-A | No Design Class Diagram exists; the Protocol and TurtleScreen are recorded in the module docstrings. |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network (Mandatory) | Pass | 34 tests; a new subprocess test blocks tkinter and imports the program; the suite also passes with tkinter blocked. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment (Optional) | Pass | mypy strict reports no issues. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused (Optional) | Pass | No runtime dependencies. |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike (Mandatory) | Pass | Titles, prompts, font and sizes defined once in constants.py. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles (Mandatory) | Pass | turtle is imported lazily inside TurtleScreen.__init__, so importing main and game needs no Tk library; game.py still depends on the Protocol. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations (Mandatory) | Pass | game.py loop, storage, screen and composition root each have one reason to change; the loop depends on the GameScreen Protocol and receives its implementation. |
## Overall Verdict
Go - Fix review: turtle is imported lazily so CI without a Tk library passes. Mandatory criteria pass (ruff, mypy --strict, 34 pytest tests, doxygen clean). CI failure cause: libtk8.6 missing on the runner.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[172778d]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/172778d22b7d78fe91eb91b145055289c87ac208
@@ -0,0 +1,68 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-013 |
| CrossReference | [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Proposed | Claude (AI) for S01 | AI as stand-in for S01 | Initial review record: Go | [172778d] |
---
## Artifact Under Review
- Instance reviewed: [MIL-003]
- Checklist used: [QC-MIL-001], [QC-LANG-001]
- Scope: full review (re-review after task 7 was added; earlier record RC-005)
- Language and domain: en / it
- Language reviewer: none
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`; the author is the same AI)
## Checklist Results
### QC-MIL-001
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate (Mandatory) | Pass | Deliverable unchanged: runnable game on the tested core. |
| 2 | Explicit Go/No-Go criteria are stated for each gate (Mandatory) | Pass | Six objectively checkable criteria, unchanged. |
| 3 | Dependencies on other milestones are explicitly mapped (Optional) | Pass | Depends on MIL-002 with a reason. |
| 4 | Each milestone is traceable to a Business Case objective or KPI (Mandatory) | Pass | Traceable to BC-001 objectives 1, 2 and success criterion 1. |
| 5 | Milestone owner and approving reviewer are identified (Mandatory) | Pass | Owner S01, approving reviewer S01 (stand-in). |
| 6 | Milestone has a defined target date consistent with project constraints (Mandatory) | Pass | 2026-10-13, within the duration constraint. |
### QC-LANG-001
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder (Mandatory) | Pass | Language en, Domain it. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list (Mandatory) | Pass | BCP 47 code en; domain it is in the registry list. |
| 3 | The content (prose and table cells) is written in the stated language (Mandatory) | Pass | Content is English. |
| 4 | The register matches the one the registry gives for the artifact type (Mandatory) | Pass | IT Executive English register for MIL. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms (Mandatory) | Pass | No DICT exists; standard software terms; stand-in decision. |
| 6 | Metadata keys, section headings, IDs and statuses are in English (Mandatory) | Pass | Structural vocabulary English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document (Mandatory) | Pass | No translated twin. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again (Mandatory) | Pass | No language change; the task row addition is recorded in Version History. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly (Mandatory) | Pass | Reviewer, AI as stand-in for S01, reads English and the software domain; open to challenge. |
| 10 | Abbreviations are spelled out on first use, in the stated language (Optional) | Pass | Abbreviations spelled out on first use in the milestone documents. |
## Overall Verdict
Go - MIL-003 with task 7 added meets every Mandatory criterion. Full re-review; the added task is a defect fix inside the accepted scope, with no change to the gate criteria.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| None | S01 | |
---
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[MIL-003]: ../../milestones/mil-003-turtle-game.md
[172778d]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/commit/172778d22b7d78fe91eb91b145055289c87ac208
+40
View File
@@ -0,0 +1,40 @@
[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"
[project]
name = "us-states-game"
version = "0.1.0"
description = "U.S. States Game: name the 50 states on a Turtle map (Udemy 100 Days of Code, day 25)."
readme = "README.md"
requires-python = ">=3.13"
dependencies = []
[project.optional-dependencies]
dev = ["pytest>=8", "ruff>=0.6", "mypy>=1.11", "yamllint>=1.35"]
[tool.setuptools.packages.find]
where = ["src"]
[tool.setuptools.package-data]
us_states_game = ["data/*.csv", "data/*.gif"]
[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]
[tool.ruff]
line-length = 88
src = ["src", "tests"]
[tool.ruff.lint]
select = ["E", "F", "W", "I", "N", "UP", "B", "D"]
ignore = ["D203", "D213"]
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["D"]
[tool.mypy]
strict = true
files = ["src", "tests"]
mypy_path = "src"
+5
View File
@@ -0,0 +1,5 @@
"""The U.S. States Game package: name the 50 states on a Turtle map.
@file __init__.py
@brief Package marker of the game.
"""
+9
View File
@@ -0,0 +1,9 @@
"""Runs the game with `python -m us_states_game`.
@file __main__.py
@brief Module entry point that calls main().
"""
from us_states_game.main import main
raise SystemExit(main())
+61
View File
@@ -0,0 +1,61 @@
"""Constants of the U.S. States Game: titles, file names and limits.
@file constants.py
@brief Titles, file names and limits used by the game.
Every value the game needs in more than one place lives here, so the
game logic and the Turtle screen never repeat a literal.
"""
from pathlib import Path
## Folder of this package.
PACKAGE_DIR = Path(__file__).resolve().parent
## Folder with the course files the game reads at run time.
DATA_DIR = PACKAGE_DIR / "data"
## CSV file with the columns state, x and y for all 50 states.
STATES_CSV_PATH = DATA_DIR / "50_states.csv"
## GIF of the blank U.S. map, registered as a Turtle shape.
MAP_IMAGE_PATH = DATA_DIR / "blank_states_img.gif"
## File written when the game ends, listing the states the player missed.
STATES_TO_LEARN_FILENAME = "states_to_learn.csv"
## Column names in the states CSV file.
STATE_COLUMN = "state"
X_COLUMN = "x"
Y_COLUMN = "y"
## Title of the game window.
SCREEN_TITLE = "U.S. States Game"
## Number of states the player has to name.
NUMBER_OF_STATES = 50
## Text the player types to leave the game early.
EXIT_COMMAND = "exit"
## Title shown while playing; filled with the guessed count and the total.
TITLE_FORMAT = "{guessed}/{total} States Correct"
## Prompt of the answer dialog.
ANSWER_PROMPT = "What's another state's name?"
## Name under which the map image is registered as a Turtle shape.
MAP_SHAPE_NAME = str(MAP_IMAGE_PATH)
## Size in pixels of the map image, and so of the game window.
SCREEN_WIDTH = 725
SCREEN_HEIGHT = 491
## Font of the state names written on the map: family, size and style.
STATE_FONT = ("Courier", 8, "normal")
## Alignment of a state name written at its coordinates.
STATE_ALIGNMENT = "center"
## Name of the logger that reports mouse click coordinates.
LOGGER_NAME = "us_states_game"
+51
View File
@@ -0,0 +1,51 @@
state,x,y
Alabama,139,-77
Alaska,-204,-170
Arizona,-203,-40
Arkansas,57,-53
California,-297,13
Colorado,-112,20
Connecticut,297,96
Delaware,275,42
Florida,220,-145
Georgia,182,-75
Hawaii,-317,-143
Idaho,-216,122
Illinois,95,37
Indiana,133,39
Iowa,38,65
Kansas,-17,5
Kentucky,149,1
Louisiana,59,-114
Maine,319,164
Maryland,288,27
Massachusetts,312,112
Michigan,148,101
Minnesota,23,135
Mississippi,94,-78
Missouri,49,6
Montana,-141,150
Nebraska,-61,66
Nevada,-257,56
New Hampshire,302,127
New Jersey,282,65
New Mexico,-128,-43
New York,236,104
North Carolina,239,-22
North Dakota,-44,158
Ohio,176,52
Oklahoma,-8,-41
Oregon,-278,138
Pennsylvania,238,72
Rhode Island,318,94
South Carolina,218,-51
South Dakota,-44,109
Tennessee,131,-34
Texas,-38,-106
Utah,-189,34
Vermont,282,154
Virginia,234,12
Washington,-257,193
West Virginia,200,20
Wisconsin,83,113
Wyoming,-134,90
1 state x y
2 Alabama 139 -77
3 Alaska -204 -170
4 Arizona -203 -40
5 Arkansas 57 -53
6 California -297 13
7 Colorado -112 20
8 Connecticut 297 96
9 Delaware 275 42
10 Florida 220 -145
11 Georgia 182 -75
12 Hawaii -317 -143
13 Idaho -216 122
14 Illinois 95 37
15 Indiana 133 39
16 Iowa 38 65
17 Kansas -17 5
18 Kentucky 149 1
19 Louisiana 59 -114
20 Maine 319 164
21 Maryland 288 27
22 Massachusetts 312 112
23 Michigan 148 101
24 Minnesota 23 135
25 Mississippi 94 -78
26 Missouri 49 6
27 Montana -141 150
28 Nebraska -61 66
29 Nevada -257 56
30 New Hampshire 302 127
31 New Jersey 282 65
32 New Mexico -128 -43
33 New York 236 104
34 North Carolina 239 -22
35 North Dakota -44 158
36 Ohio 176 52
37 Oklahoma -8 -41
38 Oregon -278 138
39 Pennsylvania 238 72
40 Rhode Island 318 94
41 South Carolina 218 -51
42 South Dakota -44 109
43 Tennessee 131 -34
44 Texas -38 -106
45 Utah -189 34
46 Vermont 282 154
47 Virginia 234 12
48 Washington -257 193
49 West Virginia 200 20
50 Wisconsin 83 113
51 Wyoming -134 90
Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

+81
View File
@@ -0,0 +1,81 @@
"""Game loop of the U.S. States Game, independent of any screen technology.
@file game.py
@brief Guess loop and the end-of-game export of the states to learn.
The loop talks to the player through the `GameScreen` port, so it runs under
test with a fake screen and no display.
"""
from collections.abc import Sequence
from pathlib import Path
from typing import Protocol
from us_states_game.constants import (
ANSWER_PROMPT,
EXIT_COMMAND,
NUMBER_OF_STATES,
STATES_TO_LEARN_FILENAME,
TITLE_FORMAT,
)
from us_states_game.states import State, find_state, get_missing_states
from us_states_game.storage import save_states_to_learn
class GameScreen(Protocol):
"""What the game loop needs from the screen."""
def ask_state_name(self, title: str, prompt: str) -> str | None:
"""Ask the player for a state name.
@param title Title of the dialog, showing the progress.
@param prompt Question shown to the player.
@return The typed text, or None if the player cancelled.
"""
...
def write_state(self, state: State) -> None:
"""Write the name of a state at its coordinates on the map.
@param state The state to write.
"""
...
def play(screen: GameScreen, states: Sequence[State]) -> list[str]:
"""Run the guess loop until all states are guessed or the player exits.
@param screen Screen used to ask for answers and to write names.
@param states All states of the game.
@return Names of the states guessed, in guessing order.
"""
guessed_states: list[str] = []
while len(guessed_states) < NUMBER_OF_STATES:
title = TITLE_FORMAT.format(guessed=len(guessed_states), total=NUMBER_OF_STATES)
answer = screen.ask_state_name(title, ANSWER_PROMPT)
if answer is None or answer.strip().casefold() == EXIT_COMMAND:
break
state = find_state(answer, states)
if state is None or state.name in guessed_states:
continue
screen.write_state(state)
guessed_states.append(state.name)
return guessed_states
def run_game(
screen: GameScreen,
states: Sequence[State],
output_path: Path = Path(STATES_TO_LEARN_FILENAME),
) -> list[str]:
"""Play the game and save the states the player missed.
@param screen Screen used to ask for answers and to write names.
@param states All states of the game.
@param output_path File that receives the states to learn.
@return Names of the states not guessed.
"""
guessed_states = play(screen, states)
missing_states = get_missing_states(states, guessed_states)
save_states_to_learn(missing_states, output_path)
return missing_states
+43
View File
@@ -0,0 +1,43 @@
"""Entry point of the U.S. States Game and its composition root.
@file main.py
@brief Wires the Turtle screen, the states and the game loop together.
"""
import argparse
import logging
from collections.abc import Sequence
from us_states_game.game import run_game
from us_states_game.storage import load_states
from us_states_game.turtle_screen import TurtleScreen
def main(argv: Sequence[str] | None = None) -> int:
"""Play the game once.
@param argv Command line arguments; defaults to `sys.argv[1:]`.
@return Process exit code, 0 on success.
"""
parser = argparse.ArgumentParser(description="U.S. States Game")
parser.add_argument(
"--show-coordinates",
action="store_true",
help="log the coordinates of every mouse click on the map",
)
args = parser.parse_args(argv)
states = load_states()
screen = TurtleScreen()
if args.show_coordinates:
logging.basicConfig(level=logging.INFO)
screen.enable_click_coordinates()
try:
run_game(screen, states)
finally:
screen.close()
return 0
if __name__ == "__main__":
raise SystemExit(main())
+54
View File
@@ -0,0 +1,54 @@
"""Pure domain logic of the U.S. States Game: states, answers and misses.
@file states.py
@brief State model, answer matching and the list of missing states.
Nothing here reads files or touches the screen, so the rules run under test
with no display and no file system.
"""
from collections.abc import Iterable
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class State:
"""A U.S. state and the position of its name on the map.
@param name Name of the state, for example "Ohio".
@param x Horizontal map coordinate of the state.
@param y Vertical map coordinate of the state.
"""
name: str
x: int
y: int
def find_state(answer: str, states: Iterable[State]) -> State | None:
"""Find the state the player named, ignoring case and surrounding spaces.
@param answer Text the player typed.
@param states The states to search.
@return The matching state, or None if the answer matches no state.
"""
wanted = answer.strip().casefold()
if not wanted:
return None
for state in states:
if state.name.casefold() == wanted:
return state
return None
def get_missing_states(
states: Iterable[State], guessed_states: Iterable[str]
) -> list[str]:
"""List the names of the states the player did not guess.
@param states All states of the game, in the order to report them.
@param guessed_states Names of the states the player guessed.
@return Names of the states not guessed, in the order of `states`.
"""
guessed = set(guessed_states)
return [state.name for state in states if state.name not in guessed]
+48
View File
@@ -0,0 +1,48 @@
"""CSV input and output of the U.S. States Game, using the csv module.
@file storage.py
@brief Loads the states from CSV and saves the states to learn.
Uses the standard library `csv` module, not pandas (see ADR-0001).
"""
import csv
from collections.abc import Iterable
from pathlib import Path
from us_states_game.constants import (
STATE_COLUMN,
STATES_CSV_PATH,
STATES_TO_LEARN_FILENAME,
X_COLUMN,
Y_COLUMN,
)
from us_states_game.states import State
def load_states(path: Path = STATES_CSV_PATH) -> list[State]:
"""Read the states and their map coordinates from a CSV file.
@param path CSV file with the state, x and y columns.
@return The states, in file order.
"""
with path.open(newline="", encoding="utf-8") as file:
return [
State(row[STATE_COLUMN], int(row[X_COLUMN]), int(row[Y_COLUMN]))
for row in csv.DictReader(file)
]
def save_states_to_learn(
missing_states: Iterable[str],
path: Path = Path(STATES_TO_LEARN_FILENAME),
) -> None:
"""Write the missing states to a one-column CSV file.
@param missing_states Names of the states the player missed.
@param path File to write; an existing file is replaced.
"""
with path.open("w", newline="", encoding="utf-8") as file:
writer = csv.writer(file)
writer.writerow([STATE_COLUMN])
writer.writerows([name] for name in missing_states)
+79
View File
@@ -0,0 +1,79 @@
"""Turtle implementation of the game screen.
@file turtle_screen.py
@brief The only module that uses turtle; draws the map and asks questions.
turtle is imported when `TurtleScreen` is created, not when this module is
imported, so the rest of the program and its tests need no Tk library.
"""
import logging
from us_states_game.constants import (
LOGGER_NAME,
MAP_SHAPE_NAME,
SCREEN_HEIGHT,
SCREEN_TITLE,
SCREEN_WIDTH,
STATE_ALIGNMENT,
STATE_FONT,
)
from us_states_game.states import State
logger = logging.getLogger(LOGGER_NAME)
def get_mouse_click_coor(x: float, y: float) -> None:
"""Log the coordinates of a mouse click on the map.
@param x Horizontal coordinate of the click.
@param y Vertical coordinate of the click.
"""
logger.info("Clicked at x=%s, y=%s", x, y)
class TurtleScreen:
"""Game screen drawn with Turtle graphics; implements `GameScreen`."""
def __init__(self) -> None:
"""Open the window with the blank map.
turtle (and so Tk) is imported here, at runtime.
"""
import turtle # noqa: PLC0415 # deferred: Tk may be missing at import time
self.screen = turtle.Screen()
self.screen.setup(SCREEN_WIDTH, SCREEN_HEIGHT)
self.screen.title(SCREEN_TITLE)
self.screen.addshape(MAP_SHAPE_NAME)
self._map = turtle.Turtle()
self._map.shape(MAP_SHAPE_NAME)
self._pen = turtle.Turtle()
self._pen.hideturtle()
self._pen.penup()
def ask_state_name(self, title: str, prompt: str) -> str | None:
"""Ask the player for a state name in a text dialog.
@param title Title of the dialog.
@param prompt Question shown to the player.
@return The typed text, or None if the player cancelled.
"""
answer: str | None = self.screen.textinput(title, prompt)
return answer
def write_state(self, state: State) -> None:
"""Write the state name on the map at its coordinates.
@param state The state to write.
"""
self._pen.goto(state.x, state.y)
self._pen.write(state.name, align=STATE_ALIGNMENT, font=STATE_FONT)
def enable_click_coordinates(self) -> None:
"""Log the coordinates of every mouse click on the map."""
self.screen.onscreenclick(get_mouse_click_coor)
def close(self) -> None:
"""Close the window."""
self.screen.bye()
+17
View File
@@ -0,0 +1,17 @@
"""Smoke test: the constants point at the assignment files that ship with the game."""
from us_states_game import constants
def test_data_files_exist() -> None:
assert constants.STATES_CSV_PATH.is_file()
assert constants.MAP_IMAGE_PATH.is_file()
def test_states_csv_has_all_states() -> None:
lines = constants.STATES_CSV_PATH.read_text(encoding="utf-8").strip().splitlines()
assert (
lines[0]
== f"{constants.STATE_COLUMN},{constants.X_COLUMN},{constants.Y_COLUMN}"
)
assert len(lines) - 1 == constants.NUMBER_OF_STATES
+104
View File
@@ -0,0 +1,104 @@
"""Tests of the guess loop and the end-of-game export in game.py."""
import csv
from collections.abc import Sequence
from pathlib import Path
from us_states_game.constants import ANSWER_PROMPT, NUMBER_OF_STATES
from us_states_game.game import play, run_game
from us_states_game.states import State
STATES = [State("Alabama", 139, -77), State("Ohio", 100, 20), State("Texas", -50, -120)]
ALL_STATES = [State(f"State {n}", n, -n) for n in range(NUMBER_OF_STATES)]
class FakeScreen:
"""Records what the loop asks and writes, and returns scripted answers."""
def __init__(self, answers: Sequence[str | None]) -> None:
self._answers = iter(answers)
self.titles: list[str] = []
self.prompts: list[str] = []
self.written: list[State] = []
def ask_state_name(self, title: str, prompt: str) -> str | None:
self.titles.append(title)
self.prompts.append(prompt)
return next(self._answers)
def write_state(self, state: State) -> None:
self.written.append(state)
def read_names(path: Path) -> list[str]:
with path.open(newline="", encoding="utf-8") as file:
return [row[0] for row in csv.reader(file)]
def test_play_writes_correct_guess_at_its_coordinates() -> None:
screen = FakeScreen(["Ohio", "exit"])
assert play(screen, STATES) == ["Ohio"]
assert screen.written == [State("Ohio", 100, 20)]
def test_play_increments_counter_in_title_after_correct_guess() -> None:
screen = FakeScreen(["ohio", "texas", "exit"])
play(screen, STATES)
assert screen.titles == [
"0/50 States Correct",
"1/50 States Correct",
"2/50 States Correct",
]
assert set(screen.prompts) == {ANSWER_PROMPT}
def test_play_uses_canonical_name_for_case_insensitive_guess() -> None:
assert play(FakeScreen(["oHiO", "exit"]), STATES) == ["Ohio"]
def test_play_asks_again_without_writing_for_wrong_guess() -> None:
screen = FakeScreen(["Atlantis", "exit"])
assert play(screen, STATES) == []
assert screen.written == []
assert screen.titles == ["0/50 States Correct", "0/50 States Correct"]
def test_play_counts_duplicate_guess_once() -> None:
screen = FakeScreen(["Ohio", "ohio", " OHIO ", "exit"])
assert play(screen, STATES) == ["Ohio"]
assert len(screen.written) == 1
assert screen.titles[-1] == "1/50 States Correct"
def test_play_ends_on_exit_command() -> None:
screen = FakeScreen(["exit"])
assert play(screen, STATES) == []
assert len(screen.titles) == 1
def test_play_ends_on_exit_command_in_any_case() -> None:
assert play(FakeScreen(["Ohio", "EXIT"]), STATES) == ["Ohio"]
def test_play_ends_when_player_cancels() -> None:
assert play(FakeScreen(["Ohio", None]), STATES) == ["Ohio"]
def test_play_ends_without_asking_again_when_all_states_are_guessed() -> None:
screen = FakeScreen([state.name for state in ALL_STATES])
assert len(play(screen, ALL_STATES)) == NUMBER_OF_STATES
assert len(screen.titles) == NUMBER_OF_STATES
def test_run_game_writes_exactly_the_missing_states(tmp_path: Path) -> None:
output = tmp_path / "states_to_learn.csv"
missing = run_game(FakeScreen(["Ohio", "exit"]), STATES, output)
assert missing == ["Alabama", "Texas"]
assert read_names(output) == ["state", "Alabama", "Texas"]
def test_run_game_writes_header_only_when_all_states_guessed(tmp_path: Path) -> None:
output = tmp_path / "states_to_learn.csv"
screen = FakeScreen([state.name for state in ALL_STATES])
assert run_game(screen, ALL_STATES, output) == []
assert read_names(output) == ["state"]
+104
View File
@@ -0,0 +1,104 @@
"""Tests of the entry point in main.py, with a fake screen."""
import subprocess
import sys
from collections.abc import Sequence
from pathlib import Path
import pytest
from us_states_game import main as main_module
from us_states_game.states import State
from us_states_game.storage import load_states
class FakeTurtleScreen:
"""Stands in for TurtleScreen: scripted answers, no display."""
instances: list["FakeTurtleScreen"] = []
answers: Sequence[str | None] = []
def __init__(self) -> None:
self._answers = iter(self.answers)
self.written: list[State] = []
self.coordinates_enabled = False
self.closed = False
FakeTurtleScreen.instances.append(self)
def ask_state_name(self, title: str, prompt: str) -> str | None:
return next(self._answers)
def write_state(self, state: State) -> None:
self.written.append(state)
def enable_click_coordinates(self) -> None:
self.coordinates_enabled = True
def close(self) -> None:
self.closed = True
@pytest.fixture
def fake_screen(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> type[FakeTurtleScreen]:
FakeTurtleScreen.instances = []
monkeypatch.setattr(main_module, "TurtleScreen", FakeTurtleScreen)
monkeypatch.chdir(tmp_path)
return FakeTurtleScreen
def test_main_writes_states_to_learn_and_returns_zero(
fake_screen: type[FakeTurtleScreen], tmp_path: Path
) -> None:
fake_screen.answers = ["Ohio", "texas", "exit"]
assert main_module.main([]) == 0
lines = (tmp_path / "states_to_learn.csv").read_text(encoding="utf-8").splitlines()
expected = [s.name for s in load_states() if s.name not in {"Ohio", "Texas"}]
assert lines == ["state", *expected]
assert len(expected) == 48
def test_main_closes_screen_after_game(fake_screen: type[FakeTurtleScreen]) -> None:
fake_screen.answers = ["exit"]
main_module.main([])
assert fake_screen.instances[0].closed
def test_main_enables_click_coordinates_with_flag(
fake_screen: type[FakeTurtleScreen],
) -> None:
fake_screen.answers = ["exit"]
main_module.main(["--show-coordinates"])
assert fake_screen.instances[0].coordinates_enabled
def test_main_leaves_click_coordinates_off_by_default(
fake_screen: type[FakeTurtleScreen],
) -> None:
fake_screen.answers = ["exit"]
main_module.main([])
assert not fake_screen.instances[0].coordinates_enabled
def test_game_and_states_modules_do_not_import_turtle() -> None:
code = (
"import sys, us_states_game.game, us_states_game.states, "
"us_states_game.storage; "
"sys.exit(1 if 'turtle' in sys.modules else 0)"
)
result = subprocess.run([sys.executable, "-c", code], check=False)
assert result.returncode == 0
def test_main_imports_without_tk_library() -> None:
src = Path(__file__).resolve().parent.parent / "src"
code = (
"import sys; "
"sys.modules['tkinter'] = None; sys.modules['_tkinter'] = None; "
f"sys.path.insert(0, {str(src)!r}); "
"import us_states_game.main, us_states_game.turtle_screen; "
"sys.exit(1 if 'turtle' in sys.modules else 0)"
)
result = subprocess.run([sys.executable, "-I", "-c", code], check=False)
assert result.returncode == 0
+41
View File
@@ -0,0 +1,41 @@
"""Tests of the pure game logic in states.py."""
from us_states_game.states import State, find_state, get_missing_states
STATES = [State("Alabama", 139, -77), State("Ohio", 100, 20), State("Texas", -50, -120)]
def test_find_state_matches_exact_name() -> None:
assert find_state("Ohio", STATES) == State("Ohio", 100, 20)
def test_find_state_ignores_case() -> None:
assert find_state("oHiO", STATES) == State("Ohio", 100, 20)
def test_find_state_ignores_surrounding_whitespace() -> None:
assert find_state(" ohio \n", STATES) == State("Ohio", 100, 20)
def test_find_state_returns_none_for_unknown_answer() -> None:
assert find_state("Atlantis", STATES) is None
def test_find_state_returns_none_for_empty_answer() -> None:
assert find_state("", STATES) is None
def test_find_state_returns_none_for_blank_answer() -> None:
assert find_state(" ", STATES) is None
def test_get_missing_states_keeps_order_of_states() -> None:
assert get_missing_states(STATES, ["Ohio"]) == ["Alabama", "Texas"]
def test_get_missing_states_is_empty_when_all_guessed() -> None:
assert get_missing_states(STATES, ["Texas", "Ohio", "Alabama"]) == []
def test_get_missing_states_returns_all_when_none_guessed() -> None:
assert get_missing_states(STATES, []) == ["Alabama", "Ohio", "Texas"]
+50
View File
@@ -0,0 +1,50 @@
"""Tests of the CSV input and output in storage.py."""
import csv
from pathlib import Path
from us_states_game.constants import NUMBER_OF_STATES, STATE_COLUMN
from us_states_game.states import State, get_missing_states
from us_states_game.storage import load_states, save_states_to_learn
def _read_rows(path: Path) -> list[list[str]]:
with path.open(newline="", encoding="utf-8") as file:
return list(csv.reader(file))
def test_load_states_returns_all_states() -> None:
assert len(load_states()) == NUMBER_OF_STATES
def test_load_states_reads_alabama_coordinates() -> None:
assert load_states()[0] == State("Alabama", 139, -77)
def test_load_states_reads_custom_path(tmp_path: Path) -> None:
path = tmp_path / "states.csv"
path.write_text("state,x,y\nOhio,10,-20\n", encoding="utf-8")
assert load_states(path) == [State("Ohio", 10, -20)]
def test_save_states_to_learn_writes_header_and_states(tmp_path: Path) -> None:
path = tmp_path / "learn.csv"
save_states_to_learn(["Ohio", "Texas"], path)
assert _read_rows(path) == [[STATE_COLUMN], ["Ohio"], ["Texas"]]
def test_save_states_to_learn_writes_only_header_when_nothing_missing(
tmp_path: Path,
) -> None:
path = tmp_path / "learn.csv"
save_states_to_learn([], path)
assert _read_rows(path) == [[STATE_COLUMN]]
def test_save_states_to_learn_lists_47_rows_after_three_guesses(
tmp_path: Path,
) -> None:
path = tmp_path / "learn.csv"
missing = get_missing_states(load_states(), ["Alabama", "Ohio", "Texas"])
save_states_to_learn(missing, path)
assert len(_read_rows(path)) - 1 == NUMBER_OF_STATES - 3
+35
View File
@@ -0,0 +1,35 @@
[English](Description) | **Dansk** | [Bahasa Melayu](Description.ms)
# Beskrivelse
Spillet følger de tre lektioner fra dag 25. Denne side forklarer, hvordan koden er bygget.
## Spilregler
- Vinduet viser det blanke kort fra `blank_states_img.gif`.
- Promptens titel viser, hvor mange delstater der er navngivet, for eksempel `14/50 States Correct`.
- Et svar matches med en delstat uden hensyn til store og små bogstaver eller mellemrum omkring.
- En rigtig delstat skrives på kortet ved sin `x` og `y` fra `50_states.csv`; et forkert eller gentaget svar spørger igen.
- `exit` eller Annuller afslutter spillet; de delstater, der ikke er navngivet, gemmes i `states_to_learn.csv`.
## Moduler
| Modul | Ansvar |
| --- | --- |
| `constants.py` | Alle konstanter: titler, filnavne, kolonnenavne, grænser |
| `states.py` | Reglerne: `State`, `find_state`, `get_missing_states`; ingen filer, ingen skærm |
| `storage.py` | Læser `50_states.csv` og skriver `states_to_learn.csv` med standardbibliotekets `csv`-modul |
| `game.py` | Gætteløkken `play` og `run_game` via en `GameScreen`-protokol |
| `turtle_screen.py` | Det eneste modul, der importerer `turtle`: kort, prompt, delstatsnavne, klikkoordinater |
| `main.py` | Indgangspunkt, der forbinder delene |
## Tests, CI og dokumentation
- `python -m pytest` kører testene med en falsk skærm, så intet vindue åbnes.
- `.gitea/workflows/run-tests.yml` kører ruff, mypy, yamllint og pytest ved hvert push og hver pull request.
- `doxygen Doxyfile` bygger kildedokumentationen i `docs/build/doxygen`.
```bash
python -m pytest
doxygen Doxyfile
```
+35
View File
@@ -0,0 +1,35 @@
**English** | [Dansk](Description.da) | [Bahasa Melayu](Description.ms)
# Description
The game follows the three lectures of day 25. This page explains how the code is built.
## Game rules
- The window shows the blank map from `blank_states_img.gif`.
- The prompt title shows how many states are named, for example `14/50 States Correct`.
- An answer is matched to a state without regard to case or surrounding spaces.
- A correct state is written on the map at its `x` and `y` from `50_states.csv`; a wrong or repeated answer asks again.
- `exit` or Cancel ends the game; the states not named are saved to `states_to_learn.csv`.
## Modules
| Module | Responsibility |
| --- | --- |
| `constants.py` | Every constant: titles, file names, column names, limits |
| `states.py` | The rules: `State`, `find_state`, `get_missing_states`; no files, no screen |
| `storage.py` | Reads `50_states.csv` and writes `states_to_learn.csv` with the standard library `csv` module |
| `game.py` | The guess loop `play` and `run_game`, working through a `GameScreen` protocol |
| `turtle_screen.py` | The only module that imports `turtle`: map, prompt, state names, click coordinates |
| `main.py` | Entry point that connects the parts |
## Tests, CI and documentation
- `python -m pytest` runs the tests with a fake screen, so no window opens.
- `.gitea/workflows/run-tests.yml` runs ruff, mypy, yamllint and pytest on every push and pull request.
- `doxygen Doxyfile` builds the source documentation into `docs/build/doxygen`.
```bash
python -m pytest
doxygen Doxyfile
```
+35
View File
@@ -0,0 +1,35 @@
[English](Description) | [Dansk](Description.da) | **Bahasa Melayu**
# Penerangan
Permainan ini mengikut tiga kuliah hari 25. Halaman ini menerangkan cara kod dibina.
## Peraturan permainan
- Tetingkap memaparkan peta kosong daripada `blank_states_img.gif`.
- Tajuk gesaan menunjukkan bilangan negeri yang dinamakan, contohnya `14/50 States Correct`.
- Jawapan dipadankan dengan negeri tanpa mengira huruf besar atau kecil atau ruang di sekelilingnya.
- Negeri yang betul ditulis pada peta di `x` dan `y` daripada `50_states.csv`; jawapan salah atau berulang ditanya semula.
- `exit` atau Cancel menamatkan permainan; negeri yang tidak dinamakan disimpan dalam `states_to_learn.csv`.
## Modul
| Modul | Tanggungjawab |
| --- | --- |
| `constants.py` | Semua pemalar: tajuk, nama fail, nama lajur, had |
| `states.py` | Peraturan: `State`, `find_state`, `get_missing_states`; tiada fail, tiada skrin |
| `storage.py` | Membaca `50_states.csv` dan menulis `states_to_learn.csv` dengan modul `csv` pustaka standard |
| `game.py` | Gelung meneka `play` dan `run_game` melalui protokol `GameScreen` |
| `turtle_screen.py` | Satu-satunya modul yang mengimport `turtle`: peta, gesaan, nama negeri, koordinat klik |
| `main.py` | Titik masuk yang menyambungkan bahagian-bahagian |
## Ujian, CI dan dokumentasi
- `python -m pytest` menjalankan ujian dengan skrin palsu, jadi tiada tetingkap dibuka.
- `.gitea/workflows/run-tests.yml` menjalankan ruff, mypy, yamllint dan pytest pada setiap push dan pull request.
- `doxygen Doxyfile` membina dokumentasi sumber ke dalam `docs/build/doxygen`.
```bash
python -m pytest
doxygen Doxyfile
```
+25
View File
@@ -0,0 +1,25 @@
[English](Home) | **Dansk** | [Bahasa Melayu](Home.ms)
# U.S. States Game
Et quizspil fra Udemys *100 Days of Code* (dag 25): navngiv de 50 delstater på et blankt kort over USA. Hvert rigtigt gæt vises på kortet; når du stopper, gemmes de delstater, du missede, i `states_to_learn.csv`.
![Det blanke kort med prompten ved 0/50 delstater](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/raw/branch/main/docs/images/game-start.png)
![Et spil i gang: 14 af 50 delstater navngivet](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/raw/branch/main/docs/images/game-in-progress.png)
## Kort fortalt
- Python 3.13 eller nyere, ingen runtime-afhængigheder
- Tests med `pytest`, ingen skærm nødvendig
- Kildedokumentation med Doxygen
- Wiki på engelsk, dansk og bahasa malaysia
## Sider
| Page | |
| --- | --- |
| [Installation](Install.da) | Sæt projektet op på Windows, Linux Debian eller MacOS og kør det |
| [Beskrivelse](Description.da) | Hvordan spillet og koden virker: regler, moduler, tests, CI og kildedokumentation |
[Repository](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game)
+25
View File
@@ -0,0 +1,25 @@
**English** | [Dansk](Home.da) | [Bahasa Melayu](Home.ms)
# U.S. States Game
A quiz game from Udemy's *100 Days of Code* (day 25): name the 50 states on a blank map of the United States. Every correct guess appears on the map; when you leave, the states you missed are saved to `states_to_learn.csv`.
![The blank map with the prompt at 0/50 states](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/raw/branch/main/docs/images/game-start.png)
![A game in progress: 14 of 50 states named](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/raw/branch/main/docs/images/game-in-progress.png)
## At a glance
- Python 3.13 or newer, no runtime dependencies
- Tests with `pytest`, no display needed
- Source documentation with Doxygen
- Wiki in English, Danish and Bahasa Malaysia
## Pages
| Page | |
| --- | --- |
| [Install](Install) | Set the project up on Windows, Linux Debian or MacOS and run it |
| [Description](Description) | How the game and the code work: rules, modules, tests, CI and source documentation |
[Repository](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game)
+25
View File
@@ -0,0 +1,25 @@
[English](Home) | [Dansk](Home.da) | **Bahasa Melayu**
# U.S. States Game
Permainan kuiz daripada *100 Days of Code* Udemy (hari 25): namakan 50 negeri di peta kosong Amerika Syarikat. Setiap jawapan yang betul dipaparkan pada peta; apabila anda berhenti, negeri yang terlepas disimpan dalam `states_to_learn.csv`.
![Peta kosong dengan gesaan pada 0/50 negeri](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/raw/branch/main/docs/images/game-start.png)
![Permainan sedang berjalan: 14 daripada 50 negeri dinamakan](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/raw/branch/main/docs/images/game-in-progress.png)
## Ringkasnya
- Python 3.13 atau lebih baharu, tiada kebergantungan masa jalan
- Ujian dengan `pytest`, tiada paparan diperlukan
- Dokumentasi sumber dengan Doxygen
- Wiki dalam bahasa Inggeris, Denmark dan Bahasa Melayu
## Halaman
| Page | |
| --- | --- |
| [Pemasangan](Install.ms) | Sediakan projek pada Windows, Linux Debian atau MacOS dan jalankannya |
| [Penerangan](Description.ms) | Cara permainan dan kod berfungsi: peraturan, modul, ujian, CI dan dokumentasi sumber |
[Repositori](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game)
+63
View File
@@ -0,0 +1,63 @@
[English](Install) | **Dansk** | [Bahasa Melayu](Install.ms)
# Installation
Opret et lokalt virtuelt miljø med navnet `.venv`, opgradér `pip` og installér projektet med testværktøjet.
## Krav
- Python 3.13 eller nyere, med `tkinter` (Turtle kræver det)
- `git`
- Valgfrit: Doxygen til at bygge kildedokumentationen
## Windows PowerShell
```powershell
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game.git
cd 025-us-states-game
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
## Linux Debian
```bash
sudo apt install python3 python3-venv python3-tk git
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game.git
cd 025-us-states-game
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
## MacOS
```bash
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game.git
cd 025-us-states-game
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
## Kør
```bash
python -m us_states_game
```
Skriv et delstatsnavn i prompten; store og små bogstaver er ligegyldige. Skriv `exit` (eller tryk Annuller) for at stoppe. De delstater, du ikke navngav, skrives til `states_to_learn.csv` i den aktuelle mappe. Tilføj `--show-coordinates` for at udskrive koordinaterne for museklik.
![Et spil i gang: 14 af 50 delstater navngivet](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/raw/branch/main/docs/images/game-in-progress.png)
## Kør testene
```bash
python -m pytest
```
Testene kræver ingen skærm.
+63
View File
@@ -0,0 +1,63 @@
**English** | [Dansk](Install.da) | [Bahasa Melayu](Install.ms)
# Install
Create a local virtual environment named `.venv`, upgrade `pip` and install the project with its test tool.
## Requirements
- Python 3.13 or newer, with `tkinter` (Turtle needs it)
- `git`
- Optional: Doxygen to build the source documentation
## Windows PowerShell
```powershell
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game.git
cd 025-us-states-game
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
## Linux Debian
```bash
sudo apt install python3 python3-venv python3-tk git
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game.git
cd 025-us-states-game
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
## MacOS
```bash
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game.git
cd 025-us-states-game
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
## Run
```bash
python -m us_states_game
```
Type a state name in the prompt; case does not matter. Type `exit` (or press Cancel) to quit. The states you did not name are written to `states_to_learn.csv` in the current folder. Add `--show-coordinates` to print the coordinates of mouse clicks.
![A game in progress: 14 of 50 states named](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/raw/branch/main/docs/images/game-in-progress.png)
## Run the tests
```bash
python -m pytest
```
The tests need no display.
+63
View File
@@ -0,0 +1,63 @@
[English](Install) | [Dansk](Install.da) | **Bahasa Melayu**
# Pemasangan
Cipta persekitaran maya tempatan bernama `.venv`, naik taraf `pip` dan pasang projek dengan alat ujiannya.
## Keperluan
- Python 3.13 atau lebih baharu, dengan `tkinter` (Turtle memerlukannya)
- `git`
- Pilihan: Doxygen untuk membina dokumentasi sumber
## Windows PowerShell
```powershell
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game.git
cd 025-us-states-game
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
## Linux Debian
```bash
sudo apt install python3 python3-venv python3-tk git
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game.git
cd 025-us-states-game
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
## MacOS
```bash
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game.git
cd 025-us-states-game
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
## Jalankan
```bash
python -m us_states_game
```
Taip nama negeri pada gesaan; huruf besar atau kecil tidak penting. Taip `exit` (atau tekan Cancel) untuk berhenti. Negeri yang tidak anda namakan ditulis ke `states_to_learn.csv` dalam folder semasa. Tambah `--show-coordinates` untuk mencetak koordinat klik tetikus.
![Permainan sedang berjalan: 14 daripada 50 negeri dinamakan](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/025-us-states-game/raw/branch/main/docs/images/game-in-progress.png)
## Jalankan ujian
```bash
python -m pytest
```
Ujian tidak memerlukan paparan.
+19
View File
@@ -0,0 +1,19 @@
**U.S. States Game**
**English**
- [Home](Home)
- [Install](Install)
- [Description](Description)
**Dansk**
- [Hjem](Home.da)
- [Installation](Install.da)
- [Beskrivelse](Description.da)
**Bahasa Melayu**
- [Utama](Home.ms)
- [Pemasangan](Install.ms)
- [Penerangan](Description.ms)