MIL-001 Baseline and repository setup #25
@@ -0,0 +1 @@
|
|||||||
|
* text=auto eol=lf
|
||||||
@@ -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
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -1,2 +1,117 @@
|
|||||||
# 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`.
|
||||||
|
|
||||||
|
> **Status:** under construction. The tooling and layout are in place; the game logic and the Turtle screen follow in the next milestones.
|
||||||
|
|
||||||
|
## 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. Type `exit` to quit; the states you did not name are written to `states_to_learn.csv` in the current folder.
|
||||||
|
|
||||||
|
## 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, game logic and the Turtle screen |
|
||||||
|
| `src/us_states_game/data/` | `50_states.csv` and `blank_states_img.gif` from the course |
|
||||||
|
| `tests/` | pytest tests |
|
||||||
|
| `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 |
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ document of a type. `Primary File` may contain a glob (e.g.
|
|||||||
| PP | Project Plan | docs/project-plan.md | 002 |
|
| PP | Project Plan | docs/project-plan.md | 002 |
|
||||||
| MIL | Milestone / Gateway | docs/milestones/*.md | 005 |
|
| MIL | Milestone / Gateway | docs/milestones/*.md | 005 |
|
||||||
| ADR | Architecture Decision Record | docs/adr/adr-NNNN-*.md | 0001 |
|
| ADR | Architecture Decision Record | docs/adr/adr-NNNN-*.md | 0001 |
|
||||||
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 007 |
|
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 008 |
|
||||||
|
|
||||||
## Languages
|
## Languages
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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"
|
||||||
@@ -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.
|
||||||
|
"""
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
"""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"
|
||||||
@@ -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
|
||||||
|
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
@@ -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
|
||||||
Reference in New Issue
Block a user