MIL-001: Project foundation #23

Merged
Tirsvad merged 10 commits from mil-001-project-foundation into main 2026-10-08 11:51:36 +02:00
25 changed files with 1871 additions and 1 deletions
+46
View File
@@ -0,0 +1,46 @@
# Continuous integration for the Snake Game.
#
# Run by Gitea Actions. The file lives in .gitea/workflows, not in
# .github/workflows: GitHub refuses a push that touches .github/workflows from a
# token without the workflow scope, and that blocks the push mirror to GitHub.
# Runs the same checks as the README, "Run the tests".
#
# The tests need no display: `snake_game.snake` does not import `turtle` until a
# real segment is created, and the tests pass fakes.
name: CI
on:
push:
pull_request:
permissions:
contents: read
jobs:
checks:
runs-on: ubuntu-latest
steps:
- name: Check out the repository
uses: actions/checkout@v4
- name: Set up Python 3.13
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
- name: Tests
run: python -m pytest
- name: Lint
run: python -m ruff check src tests
- name: Format check
run: python -m ruff format --check src tests
- name: Types
run: python -m mypy
+34
View File
@@ -0,0 +1,34 @@
# Personal tokens: never commit or import this file
.env
# Virtual environment
.venv
venv
# Byte-compiled and cached files
__pycache__
*.py[cod]
*$py.class
# Packaging and build output (build/ also holds the Doxygen HTML)
build/
dist/
*.egg-info/
*.egg
.eggs/
pip-wheel-metadata/
# Test, lint and type-check caches
.pytest_cache/
.ruff_cache/
.mypy_cache/
.coverage
.coverage.*
htmlcov/
# Editors and operating systems
.idea/
.vscode/
*.swp
.DS_Store
Thumbs.db
+3
View File
@@ -0,0 +1,3 @@
[submodule "framework"]
path = framework
url = ssh://git@git.tirsystem.com:10022/TirSystem/SQA-QC-Framework.git
+37
View File
@@ -0,0 +1,37 @@
# Doxygen configuration for the snake game (Python sources in src/).
#
# Build: doxygen Doxyfile
# Output: build/doxygen/index.html
#
# Only the settings that differ from the Doxygen defaults are listed. A warning
# (for example an undocumented public item) fails the build.
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "Snake Game"
PROJECT_BRIEF = "Snake game from Udemy's 100 Days of Code (day 21)"
OUTPUT_DIRECTORY = build
HTML_OUTPUT = doxygen
# Python sources are documented with Doxygen commands in docstrings and in
# "##" comments.
OPTIMIZE_OUTPUT_JAVA = YES
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
INPUT = src
FILE_PATTERNS = *.py
RECURSIVE = YES
SOURCE_BROWSER = YES
GENERATE_HTML = YES
GENERATE_LATEX = NO
HAVE_DOT = NO
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_IF_INCOMPLETE_DOC = YES
# NO: with YES, Doxygen also asks for an @return on every "-> None" function.
WARN_NO_PARAMDOC = NO
WARN_AS_ERROR = FAIL_ON_WARNINGS
+153 -1
View File
@@ -1,2 +1,154 @@
# 021-snake-game # Snake Game (Day 21)
The classic Snake game, built object-oriented with Python's `turtle` module. It is
the day-21 assignment of Udemy's *100 Days of Code: The Complete Python Pro
Bootcamp*: a snake moves across a black 600 by 600 screen by itself and is steered
with the arrow keys; it eats food, grows, and a score is shown at the top; the game
is over when the head passes the wall or touches its own tail. Day 21 teaches class
inheritance (`Food` and `Scoreboard` inherit from `Turtle`) and slicing (the tail is
`segments[1:]`).
The game has no runtime dependencies. The code keeps the names of the lectures
(`Snake`, `create_snake`, `move`, `up`, `down`, `left`, `right`, `segments`,
`head`, `game_is_on`, `Food`, `Scoreboard`, `refresh`, `extend`, `increase_score`,
`game_over`) so that you can compare it with your own solution.
This repository continues
[020-snake-game](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/020-snake-game)
and starts from its finished game; `docs/project-plan.md` tells how the work is split.
> **Status:** the project foundation is in place (environment, constants, tests,
> source documentation, continuous integration). The game itself, `python -m
> snake_game`, is added by the next milestone, `MIL-002`.
## Requirements
- Python 3.13 or newer, with `tkinter` (the `turtle` module needs it).
- `git`, to clone the repository.
- Optional: [Doxygen](https://www.doxygen.nl/) to build the source documentation.
- No runtime dependencies. The development tools (`pytest`, `ruff`, `mypy`) are
installed into the virtual environment by the `dev` extra.
## Set up
Clone the repository, then create a local virtual environment `.venv` in its
root, upgrade `pip` and install the project with its development tools. The
`.venv` folder is ignored by git.
```bash
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game.git
cd 021-snake-game
```
### Windows powershell
```powershell
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, allow scripts for this
window only with `Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned`
and activate again. Python from python.org includes `tkinter`.
### Linux debian
Debian 13 or newer ships Python 3.13. On older releases install Python 3.13
separately.
```bash
sudo apt install python3 python3-venv python3-tk
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
### MacOS
```bash
brew install python@3.13 python-tk@3.13
python3.13 -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 snake_game
```
The game is not in the repository yet: `python -m snake_game` works once `MIL-002`
is merged, and this section is then completed with the keys, the food, the score
and the game-over rules.
## Run the tests
The tests need no display: they use fakes instead of real turtles.
```bash
pytest
```
The same checks that continuous integration runs:
```bash
python -m pytest
python -m ruff check src tests
python -m ruff format --check src tests
python -m mypy
```
## Continuous integration
`.gitea/workflows/ci.yml` runs on Gitea Actions on every push and on every pull
request. It sets up Python 3.13, upgrades `pip`, installs `.[dev]`, then runs
`pytest`, `ruff` (lint and format check) and `mypy`. It does not build the source
documentation: run `doxygen Doxyfile` yourself, as the next section shows. No
step opens a turtle window.
The workflow lives in `.gitea/workflows` and not in `.github/workflows`, so
GitHub does not run it and pushing to the GitHub mirror needs no workflow
permission.
## Build the source documentation
The source is documented with Doxygen comments and the `Doxyfile` in the root.
Install Doxygen (`winget install DimitriVanHeesch.Doxygen` on Windows,
`sudo apt install doxygen` on Debian, `brew install doxygen` on macOS), then:
```bash
doxygen Doxyfile
```
The HTML is written to `build/doxygen/index.html`. A warning fails the build.
## Project layout
```text
.
├── .gitea/workflows/ci.yml continuous integration (Gitea Actions)
├── docs/ business case, plan, milestones, reviews
├── src/snake_game/ the game
│ ├── __init__.py
│ └── constants.py every constant of the game
├── tests/ pytest tests
│ └── test_constants.py
├── Doxyfile source documentation settings
├── LICENSE
├── pyproject.toml project configuration
└── README.md
```
The game modules (`snake.py`, `food.py`, `scoreboard.py`, `main.py`,
`__main__.py`) and their tests are added by `MIL-002`.
## License
GNU Affero General Public License v3.0 only. See [LICENSE](LICENSE).
+59
View File
@@ -0,0 +1,59 @@
# Artifact Registry
This project's artifact state. Types, short names and `CrossReference
Candidates` come from the framework catalog
(`framework/registry/artifact-catalog.md`); this file only records where
each document lives in *this* project and the next version to use.
Delete rows for types you don't use. Add a row the first time you create a
document of a type. `Primary File` may contain a glob (e.g.
`docs/uc-*/uc.md`); `framework/scripts/find-crossreferences.sh` reads it.
| Short Name | Artifact Type | Primary File | Next Available Version |
| --- | --- | --- | --- |
| BC | Business Case | docs/business-case.md | 002 |
| SA | Stakeholder Analysis | docs/stakeholder-analysis.md | 002 |
| PP | Project Plan | docs/project-plan.md | 002 |
| MIL | Milestone / Gateway | docs/milestones/*.md | 004 |
| DICT | Domain Dictionary | docs/dictionary.md | 002 |
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 008 |
## Languages
Set the PO language when the project starts; `project-planning` asks for it
if it is missing. An artifact of a type marked "Written in the PO language"
exists once, in that language, under its normal name (`business-case.md`); the
`artifact` skill ("One file per artifact") has the rule.
| Setting | Value |
| --- | --- |
| PO language | en |
| PO domain | it |
| High-level register | IT Executive English |
| Technical register | IT Professional English |
Every artifact of a type marked "Yes" below states its language and domain in
its `Language` and `Domain` Metadata rows; `new-artifact.sh` fills them from
`PO language` and `PO domain`. `Language` is a BCP 47 code (`da`, `en`).
`Domain` is a value from this list; add a row to introduce a domain, so a
reviewer can see at once which professional vocabulary a document uses.
| Domain | Meaning |
| --- | --- |
| it | Software and IT |
| medical | Healthcare and medical devices |
| construction | Construction and civil engineering |
| Artifact types | Register | Written in the PO language |
| --- | --- | --- |
| BC, KPI, PP, MIL | IT Executive English | Yes |
| SA, BMC, BPMN, UCD, US, UC, SSD, DM, RA, GOV, DICT | IT Professional English | Yes |
| OC, SD, DCD, ERD, ADR, TM, RC, QC, source code | IT Professional English | No |
## Notes
- "Next Available Version" is the zero-padded (3-digit) version to use the
*next* time a new document of that type is created. Increment it only when
a brand-new document is created, not when an existing document's
`## Version History` gets a row.
- `ADR` uses 4 digits (`0001`); `RC` is sequential across all artifact types.
+186
View File
@@ -0,0 +1,186 @@
# Business Case: Snake Game (Day 21)
## Metadata
| Key | Value |
| --- | --- |
| ID | BC-001 |
| CrossReference | [SA-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version, reviewed in RC-001 (Go) | [f13d004] |
---
## Executive Summary
Snake Game (Day 21) is the day-21 assignment of Udemy's *100 Days of Code: The Complete Python Pro Bootcamp*: the classic Snake game, built in an object-oriented way with Python's `turtle` module. Day 21 teaches class inheritance and slicing and applies them to the game in five lectures: inheritance and slicing, detecting collisions with the food, the scoreboard, the wall, and the tail.
This repository continues the day-20 repository [020-snake-game], whose `main` already holds the finished game (food, score and game over included) with its tests, source documentation and review records. On 2026-10-08 S01 decided, in chat, to start this repository from that finished `main` and not to rebuild the game. The project therefore adopts the day-20 base, gives it the identity of this repository (name, links, description, README), and checks every behaviour against the day-21 lecture summaries, whose numbers the day-20 repository had to assume. The work is planned in three milestones, each delivered by one branch and one pull request. The game has no runtime dependencies.
## Methodological and Standards Foundation
- **Process:** the Software Quality Assurance (SQA) and Quality Criteria (QC)
framework mounted at `framework/`: Business Case, Stakeholder Analysis,
Project Plan, milestones, tasks synced as issues, then code, each step
reviewed before the next. Analysis follows Larman, *Applying UML and
Patterns*.
- **Quality model:** ISO/IEC 25010:2023; every QC criterion is tagged with a
characteristic of it.
- **Code:** Python Enhancement Proposals (PEP) 8, 257 and 484, reviewed against `QC-PY-001`; comments in Doxygen style; tests with pytest.
- **Domain terms:** the lectures' own terms and names are used and recorded in the Domain Dictionary [DICT-001] (screen, snake, segment, head, body, tail, move, direction, reversal, food, refresh, eat, grow, score, scoreboard, wall, touch, game over, inheritance, and the names `create_snake`, `up`, `down`, `left`, `right`, `game_is_on`, `Food`, `Scoreboard`).
## Problem Statement
- The course shows the code only inside lecture videos, and the day-21 lectures change the same code several times (the food, the scoreboard, the wall, the tail). Nobody can run or compare the finished game without retyping it.
- A loose script cannot be run by someone else without guessing the Python version, the environment and the way to start it.
- A turtle program opens a window, so it is normally not tested, and mistakes in the rules (a snake that grows at the wrong place, a touch that is never detected) are found only by watching.
- The numbers of day 21 (size of the food, the distances of the two collisions, the wall) were assumptions in the day-20 repository, because it had only an outline of day 21. They have not yet been compared with the lecture summaries.
- A repository without description, topics or README is hard to find and hard to judge for the people who browse for ideas.
## Business Opportunity
A single finished, reproducible repository shows the whole path from lecture to documented, tested code. Starting from the finished base saves the rebuild, so the effort goes into what is new here: checking the game against the day-21 lectures and making the repository stand on its own. It can be compared with the solutions of other participants, shared, and reused as the pattern for the following days of the course.
## Objectives
| # | Objective |
| --- | --- |
| 1 | Keep the behaviour of the day-20 base: a 600 by 600 black window titled "My Snake Game"; a snake of three square segments at (0, 0), (-20, 0) and (-40, 0); a move of 20 pixels every 0.1 seconds; arrow keys that turn the head; and no reversal onto the snake |
| 2 | Deliver the food, eating, growth and score of the day-21 lectures: a blue circle of 10 by 10 pixels (half the size of a default turtle) at a random place inside the wall, so never at the very edge of the screen; the food is eaten when the head is closer than 15 pixels, moves to a new random place, makes the snake one segment longer, and raises the score on the scoreboard by 1 |
| 3 | Deliver the game over of the day-21 lectures: the game is over when the head passes the wall (280 pixels from the centre) or comes closer than 10 pixels to a segment of the tail; the text GAME OVER is shown in the middle of the window with the score still visible |
| 4 | Show the lessons of day 21 in the code: `Food` and `Scoreboard` inherit from `Turtle`, and the tail check loops over a slice of the segments that leaves out the head |
| 5 | Keep the assignment's structure and names: `Food` with `refresh`, `Scoreboard` with `increase_score`, `update_scoreboard` and `game_over`, `Snake` with `create_snake`, `add_segment`, `extend`, `move`, `up`, `down`, `left`, `right`, a `segments` list and a `head`, constants in `constants.py`, and a main flow that uses `screen`, `snake` and `game_is_on` |
| 6 | Provide a reproducible environment: Python 3.13 or newer, a local `.venv`, a `pyproject.toml`, and zero runtime dependencies |
| 7 | Prove the behaviour with pytest tests that need no display |
| 8 | Document the project: Doxygen comments in the source with a `Doxyfile`, and a README with set-up instructions for Windows PowerShell, Linux Debian and macOS |
| 9 | Keep every step traceable: one branch and one pull request per milestone, each pull request closing the issues it completes |
| 10 | Publish the repository with a description and topics |
## Scope
### In Scope
- Adopting the finished game of [020-snake-game] (source, tests, configuration, continuous integration workflow) as the base of this repository, and recording every difference from it.
- The five lectures of day 21: inheritance and slicing, detecting collisions with the food, the scoreboard, the wall, and the tail, as far as the lecture summaries give them.
- Checking each rule of the game against the lecture summaries, and correcting the base where it differs.
- Constants in `constants.py`; source in `src/`, tests in `tests/`, documents in `docs/`.
- `pyproject.toml`, Python `.gitignore`, `Doxyfile`, `README.md` following the Product Owner's template, a continuous integration (CI) workflow.
- Repository description and topics on the git host.
### Out of Scope
- Anything the lectures do not cover: sound, a menu, high-score storage between games (no lecture of day 21 stores one), restarting after game over, levels, configurable speed or window size.
- Rebuilding the game from the day-20 state; the finished base is used as it is.
- Keeping this repository and [020-snake-game] in step after today: a later fix in one of them is not carried to the other.
- Packaging for or publishing to the Python Package Index (PyPI).
- Runtime dependencies of any kind.
- Using or testing the tokens in `.env`; the file is for personal use only and is never imported by the project.
## Expected Benefits
### Tangible Benefits
- A finished game (day 21) that runs with one command after the README steps.
- A test suite that can run in continuous integration without a display.
- Generated source documentation.
- A repository page with description, topics and README.
- A written comparison of the game with the day-21 lectures, which the day-20 repository does not have.
### Intangible Benefits
- Practice with class inheritance, slicing and the `turtle` coordinate system, which is the aim of the lectures.
- A pattern for the following days of the course.
- Confidence from a step-by-step, reviewed delivery.
## Strategic Alignment
The project supports the participant's goal of finishing the bootcamp with repositories that other people can read, run and learn from, and it exercises the framework's rule that planning, review and code stay in step.
## Success Criteria
| # | Criterion | Target | Measure |
| --- | --- | --- | --- |
| 1 | The day-20 behaviour is kept | Window 600 by 600, black, titled "My Snake Game"; 3 segments at (0, 0), (-20, 0), (-40, 0); every move takes each segment 20 pixels and each segment takes the place of the one before it; the head turns to 90, 270, 180 and 0 degrees for up, down, left and right; a reversal is ignored | Manual run by S01 against the Go/No-Go list of [MIL-003], plus the matching tests |
| 2 | Food, eating and score follow the lectures | The food is a blue circle of 10 by 10 pixels at a random place inside the wall, so never at the very edge of the screen; when the head is closer than 15 pixels the food moves to a new random place, the snake grows by one segment at the place of its last segment and the score rises by 1 | Manual run by S01 against the Go/No-Go list of [MIL-003], plus the matching tests |
| 3 | Game over follows the lectures | The game ends when the head passes 280 pixels from the centre on any side or comes closer than 10 pixels to a segment behind the head; GAME OVER is shown in the middle with the score visible; the window closes on a click | Manual run by S01 against the Go/No-Go list of [MIL-003], plus the matching tests |
| 4 | The lessons of day 21 are visible | `Food` and `Scoreboard` are subclasses of `turtle.Turtle`; the tail check loops over `segments[1:]` | Review of `src/` |
| 5 | Tests are green and need no display | 100% of tests pass; 0 tests open a window; at least one test per public function and method of the logic modules | `pytest` exit code 0 locally and in CI |
| 6 | The set-up steps work | A fresh clone reaches a green `pytest` by following the README alone, on Windows PowerShell (by S01) and on Linux (by CI) | One run per operating system, recorded in the pull request |
| 7 | Source documentation builds | `doxygen Doxyfile` ends with 0 warnings | Doxygen output |
| 8 | No runtime dependencies | 0 entries in `[project].dependencies` | `pyproject.toml` |
| 9 | Names follow the assignment | 100% of the names listed in objective 5 exist with that spelling | Review of `src/` against objective 5 |
| 10 | Steps are traceable | 3 of 3 milestones merged by pull request, each description with one `Closes #N` line per completed issue | Pull request list and issue states |
| 11 | The repository page is complete | Non-empty description and at least 5 topics | Git host |
| 12 | The base is adopted without hidden change | Every difference between the adopted files and [020-snake-game] is listed in the pull request that introduces it | Pull request descriptions |
## Risks
| Risk | Impact | Mitigation |
| --- | --- | --- |
| `tkinter` is missing from the Python installation (typical on Debian) | The game cannot start | README lists `python3-tk` for Debian; the `snake` module does not import `turtle` at module level, so tests do not need it |
| Debian 12 ships Python 3.11, below the required 3.13 | Linux set-up fails | README states Debian 13 or newer, or a separately installed Python 3.13 |
| A turtle window cannot be opened in continuous integration | The tests cannot cover the game | `Snake` receives its segment factory as a parameter, so tests pass fakes; only `main` opens a window |
| The git host has no Actions runner | The continuous integration workflow is never executed | Provide the workflow file and run the same commands locally; recorded as an open issue of [PP-001] |
| Closing the window during the animation loop ends in a traceback (`_tkinter.TclError` or `turtle.Terminator`) | The game looks broken when it is quit | The adopted main flow exits quietly when the window is closed; [MIL-002] checks it |
| Author and reviewer are the same person (S01) | A defect can pass review unnoticed | Review against the QC checklists, record each review as an `RC-*`, and let the pull request be the second look |
| The lectures are available only as the summaries in the request | The game differs from the video | S01 compares the finished game with the video at the [MIL-003] Go/No-Go |
| The day-20 base was written against assumed day-21 numbers | A value of the base (size of the food, distances, range of the random place, text of game over) differs from the lectures | [MIL-003] checks each value against the lecture summaries and corrects the base where it differs |
| `Food` and `Scoreboard` inherit from `turtle.Turtle`, so importing them loads `turtle` and `tkinter` | A machine without `tkinter` cannot run the tests of these classes | The adopted tests install a fake `turtle` module before they import the classes |
| The random place of the food makes a test unreliable, or puts the food under the snake | A test fails now and then, or the game looks wrong | The random place comes from one function that the tests replace; whether the food may appear under the snake is an open issue of [PP-001] |
| The adopted files drift away from [020-snake-game] | A fix made in one repository is missing in the other | Out of scope by decision; each pull request lists the differences from the base |
| Tokens in `.env` leak into the repository | Credentials exposed | `.env` is in `.gitignore`, is never imported, and is not part of any task |
## Assumptions
- Python 3.13 or newer with `tkinter` is available on the machines that run the game.
- S01 is the only person who reviews and accepts artifacts.
- The git host is the Tirsvad Gitea instance, and its issues and milestones are used for tracking.
- The day-21 lecture summaries in the request are the specification of day 21; the video is the tie-breaker when a detail is missing.
- The finished `main` of [020-snake-game] is correct as far as its own tests and review records show, and is the base for every file that the milestones adopt.
## Constraints
- Python 3.13 or newer, in a virtual environment (`venv`).
- pytest for tests; `constants.py` for constants; `pyproject.toml` for project configuration; a Python `.gitignore`; Doxygen comments in the source and a `Doxyfile`.
- Folder structure `src/`, `tests/`, `docs/`.
- No runtime dependencies unless needed.
- Plan window from 2026-10-08 to 2026-10-16 (proposed, see [PP-001]), about one week of S01's spare time.
- Nothing is committed, pushed or merged without the Product Owner's request; changes are reviewed in the working tree first.
- The plan gate holds: no file under `src/` or `tests/` before an accepted, reviewed milestone that lists the task.
## Cost–Benefit Assessment
The assessment is qualitative on purpose: this is an unpaid learning project with one participant, so money does not measure either side.
| Costs | Benefits |
| --- | --- |
| About one week of S01's spare time, including reviews | A finished and shareable repository (objectives 1 to 10) |
| Review effort for the planning documents, which is large compared with the work left on the game | A traceable, repeatable way of working that later days can reuse |
| Two repositories that hold the same code and can drift apart | No rebuild of a game that already exists and is tested |
| Doxygen and pytest as development tools (not runtime) | Source documentation and automatic checks |
## Stakeholders
| Stakeholder ID (SA) | Interest in this project |
| --- | --- |
| S01 | Wants a correct, tested and documented solution of the assignment: objectives 1 to 10 |
| S02 | Needs readable, runnable code with the assignment's names and README instructions (objectives 2, 3, 5, 6 and 8) |
| S03 | Needs a clear repository page and nothing to install (objectives 6, 8 and 10) |
## Recommendation
Proceed — the work left is small (adopt a finished and tested base, check it against the day-21 lectures, and publish it), the cost is about one week of the Product Owner's time, and the result is a reusable, documented repository.
---
[SA-001]: ./stakeholder-analysis.md
[DICT-001]: ./dictionary.md
[PP-001]: ./project-plan.md
[MIL-002]: ./milestones/mil-002-adopt-the-game.md
[MIL-003]: ./milestones/mil-003-check-against-day-21.md
[020-snake-game]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/020-snake-game
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
+66
View File
@@ -0,0 +1,66 @@
# Domain Dictionary: Snake Game (Day 21)
## Metadata
| Key | Value |
| --- | --- |
| ID | DICT-001 |
| CrossReference | [BC-001], [SA-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version, reviewed in RC-003 (Go) | [f13d004] |
---
## Purpose and Scope
Maps each Product Owner (PO) term to its professional information technology (IT) term. PO language: `en` (domain `it`), from the registry's `Languages` section. The PO terms are the words of the lectures of days 20 and 21 as the planning documents use them; the IT terms are the names in the code. The dictionary covers the vocabulary of the game; it exists so that the planning documents use one word for one thing and so that S02 can find the lectures' names in the code. It is adopted from the dictionary of the day-20 repository and gains the terms refresh and inheritance, which the day-21 lectures introduce.
## Dictionary
| PO term | Language | IT term | Definition | Used as PO term in | Used as IT term in |
| --- | --- | --- | --- | --- | --- |
| window | en | Tk window | The desktop window that holds the screen and is opened when the game starts. | BC, SA, PP, MIL | PY |
| screen | en | `Screen` | The drawing area that the game sets up (size, colour, title) and on which the snake is shown. | BC, SA, PP, MIL | PY |
| snake | en | `Snake` | The creature the player steers, made of segments. | BC, SA, PP, MIL | PY |
| segment | en | `Turtle` | One white square of the snake. | BC, SA, PP, MIL | PY |
| head | en | `head` | The first segment, which leads the snake and is turned by the arrow keys. | BC, SA, PP, MIL | PY |
| tail | en | `segments[1:]` | Every segment behind the head; the game is over when the head touches one of them. | BC, SA, PP, MIL | PY |
| body | en | `segments` | All segments of the snake, the head included, in order, the head first. | BC, SA, PP, MIL | PY |
| starting position | en | `STARTING_POSITIONS` | One of the three places at which a segment is drawn when the game starts. | BC, MIL | PY |
| move | en | `move` | One pass in which each segment takes the place of the one before it and the head goes forward by the move distance. | BC, SA, PP, MIL | PY |
| move distance | en | `MOVE_DISTANCE` | How far the head goes in one move, 20 pixels. | BC, MIL | PY |
| direction | en | `heading` | The way the head points: up, down, left or right. | BC, SA, PP, MIL | PY |
| reversal | en | opposite heading | A turn by 180 degrees, so that the head would run into the segment behind it. | BC, SA, PP, MIL | PY |
| arrow key | en | key name `"Up"`, `"Down"`, `"Left"`, `"Right"` | One of the four keys with which the player turns the head. | BC, SA, PP, MIL | PY |
| key binding | en | `onkey` | The link between an arrow key and the method that turns the head. | BC, PP, MIL | PY |
| animation loop | en | `while game_is_on` loop | The loop that refreshes the screen, waits and makes one move, again and again. | BC, PP, MIL | PY |
| refresh delay | en | `REFRESH_DELAY_SECONDS` | The wait between two moves, 0.1 seconds. | BC, MIL | PY |
| food | en | `Food` | The small blue circle that the snake eats; it is shown at a random place. | BC, SA, PP, MIL | PY |
| refresh | en | `refresh` | The food moves to a new random place; it happens when the game starts and every time the food is eaten. | BC, SA, MIL | PY |
| eat | en | `FOOD_COLLISION_DISTANCE` | The head comes closer to the food than this distance, which makes the snake grow and the score rise. | BC, MIL | PY |
| grow | en | `extend` | The snake gets one more segment, at the place where its last segment is. | BC, SA, MIL | PY |
| score | en | `score` | The number of foods the snake has eaten in this game. | BC, SA, PP, MIL | PY |
| scoreboard | en | `Scoreboard` | The text at the top of the screen that shows the score. | BC, SA, MIL | PY |
| wall | en | `WALL_LIMIT` | The line on every side of the playing field, 280 pixels from the centre; the head must stay inside it and the food is shown inside it. | BC, SA, PP, MIL | PY |
| touch | en | `TAIL_COLLISION_DISTANCE` | The head comes closer to a segment of the tail than this distance. | BC, MIL | PY |
| game over | en | `game_over` | The end of the game, shown with the text GAME OVER, when the head passes the wall or touches the tail. | BC, SA, PP, MIL | PY |
| inheritance | en | subclass of `Turtle` | A class takes over the attributes and methods of another class; `Food` and `Scoreboard` take over those of `Turtle`. | BC, SA, MIL | PY |
## Rules
- The Business Case, Stakeholder Analysis, Project Plan and milestones use the PO term; the source code and its tests use the IT term. The other design artifacts (Domain Model, Operation Contract, Sequence Diagram, Design Class Diagram, ERD) do not exist in this project.
- One IT term per PO term and one PO term per IT term; no synonyms.
- The planning documents use British spelling (colour, centre); identifiers such as `color` follow the `turtle` module and the lectures.
- A code identifier written in backticks in a planning document is an IT term and is allowed there.
- "Step" is not a PO term of the game. In the planning documents it means a step of the project (a task, a milestone), never a move of the snake.
- "Base" is not a PO term of the game. In the planning documents it means the finished `main` of the day-20 repository that this project adopts, never a part of the game.
---
[BC-001]: ./business-case.md
[SA-001]: ./stakeholder-analysis.md
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
@@ -0,0 +1,95 @@
# MIL-001: Project foundation
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-001 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version, reviewed in RC-004 (Go) | [f13d004] |
---
## Purpose
This gate decides whether the repository is ready to hold the game: a fresh clone can be set up from the README, the tests and the documentation build run, every constant of the game lives in one module, and the repository page says what the project is. The files are adopted from the base ([020-snake-game], `main`) and given the identity of this repository. The work is delivered on the branch `mil-001-project-foundation` and one pull request.
## Deliverable
The repository files that carry no game logic yet: `pyproject.toml`, the Python `.gitignore`, the package `src/snake_game/` with `constants.py`, `tests/test_constants.py`, `README.md` following the Product Owner's template, `Doxyfile`, and the continuous integration workflow `.gitea/workflows/ci.yml`. The repository description and topics on the git host are set.
Each adopted file is copied from the base and changed only where the identity of this repository requires it (project name, description, repository links, day number). The pull request lists every difference from the base.
Proposed repository description and topics, for S01 to confirm before they are set:
- Description: "Snake game in Python with turtle graphics and object-oriented design: the snake eats food, grows, keeps a score and ends at the wall or at its own tail. Day 21 of Udemy's 100 Days of Code Python bootcamp, with pytest tests and Doxygen docs. No runtime dependencies."
- Topics: `100-days-of-code`, `doxygen`, `education`, `game`, `oop`, `pytest`, `python`, `python-bootcamp`, `python3`, `snake-game`, `turtle-graphics`, `udemy`.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | In a fresh clone, `python -m venv .venv`, `python -m pip install --upgrade pip` and `python -m pip install -e ".[dev]"` succeed in Windows PowerShell | All three commands exit 0 | Any command fails |
| 2 | `pytest` runs | Exit code 0, at least one test of `constants.py`, no window opened | Failing test, or no test of `constants.py` |
| 3 | `pyproject.toml` states the Python version and the dependencies | `requires-python = ">=3.13"`, `dependencies = []`, a `dev` extra with pytest, and a repository URL that names this repository | Any of the four is missing or different |
| 4 | The `.gitignore` protects local files | `git check-ignore .venv .env __pycache__` lists all three | One of them is not ignored |
| 5 | `constants.py` holds the values of the lectures | Screen width, height, colour and title; segment shape and colour; the three starting positions; the move distance; the four directions; the refresh delay; the food shape, size, colour and speed; the wall; the eating distance; the scoreboard label, colour, position, alignment and font; the touch distance; the game-over text and place are constants with Doxygen comments | A value of the list is missing or has no Doxygen comment |
| 6 | `doxygen Doxyfile` builds the source documentation | Ends with 0 warnings and writes HTML for `src/` | Any warning, or no output |
| 7 | The README follows the Product Owner's template | Every section title of the template in the given order, with commands for Windows PowerShell, Linux Debian and macOS | A heading is missing, out of order, or a section has no commands |
| 8 | The continuous integration (CI) workflow exists | `.gitea/workflows/ci.yml` installs `.[dev]` and runs `pytest`, `ruff` and `mypy` on Python 3.13, and nothing under `.github/workflows` exists | No workflow, or it does not run the tests, or a file exists under `.github/workflows` |
| 9 | The repository page is complete | Description is non-empty and there are at least 5 topics on the git host | Description empty or fewer than 5 topics |
| 10 | The adopted files are traceable to the base | The pull request lists every difference between each adopted file and the base, or says that there is none | A difference that the list does not name |
| 11 | The code is reviewed | `RC-*` against `QC-PY-001` has the verdict `Go` | Verdict `No-Go` or `Go-with-conditions` |
| 12 | No secret is in the change | `.env` is not tracked and no token appears in any changed file | A token is found in the diff |
## Dependencies
| Depends on | Reason |
| --- | --- |
| [PP-001] accepted | The plan schedules this gateway; the plan-first gate needs it before any code |
| This milestone accepted with a `Go` review | The plan-first gate allows no file under `src/` or `tests/` before that |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 6: reproducible environment, no runtime dependencies | [BC-001], criteria 6 and 8 in Success Criteria |
| Objective 7: tests without a display | [BC-001], criterion 5 in Success Criteria |
| Objective 8: Doxygen and README | [BC-001], criteria 6 and 7 in Success Criteria |
| Objective 10: repository page | [BC-001], criterion 11 in Success Criteria |
| Objective 9: traceable steps; the base is adopted without hidden change | [BC-001], criteria 10 and 12 in Success Criteria |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 |
## Target Date
2026-10-09 — first of three gateways, inside the one-week plan of [PP-001] that ends 2026-10-16.
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Add pyproject.toml for the Day 21 repository | Adopt `pyproject.toml` from the base for the `snake-game` project: `requires-python = ">=3.13"`, an empty `dependencies` list, an optional `dev` extra with pytest, ruff and mypy, the `src` layout for the package `snake_game`, the pytest settings (`testpaths = ["tests"]`), and a description and repository URL that name this repository and day 21. Serves objective 6 of the Business Case: a reproducible environment without runtime dependencies. | No | |
| 2 | Add the Python .gitignore for the Day 21 repository | Adopt the Python `.gitignore` from the base: bytecode, `.venv/`, build and packaging output, pytest, ruff, mypy and Doxygen output. It also ignores `.env`, so the personal tokens can never be committed or become part of the project. | No | |
| 3 | Adopt constants.py and its test | Copy `src/snake_game/__init__.py`, `src/snake_game/constants.py` and `tests/test_constants.py` from the base. The constants hold every value of the lectures as `UPPER_SNAKE` constants with Doxygen comments, the day-21 values included (food, wall, eating distance, scoreboard, touch distance, game-over text). Values that the day-21 lecture summaries fix differently are corrected in MIL-003, not here. | No | |
| 4 | Add the README for the Day 21 repository | Adopt `README.md` from the base and rewrite its identity for this repository (name, day 21, clone address). Keep the Product Owner's template (Requirements, Set up for Windows PowerShell, Linux Debian and macOS, Run, Run the tests, Continuous integration, Build the source documentation, Project layout, License). Document creating a local `.venv`, `python -m pip install --upgrade pip` and `python -m pip install -e ".[dev]"`; name `python3-tk` and Debian 13 for Linux. The Run section is finished in MIL-003. Serves S02 and S03. | No | |
| 5 | Add the Doxyfile for the Day 21 repository | Adopt the `Doxyfile` from the base: it reads `src/`, writes to `build/doxygen`, extracts documentation for Python (Doxygen comment style, `OPTIMIZE_OUTPUT_JAVA`) and treats warnings as failures; the project brief names day 21. The README documents the command `doxygen Doxyfile`. | No | |
| 6 | Add the continuous integration workflow | Adopt `.gitea/workflows/ci.yml` (run by Gitea Actions) from the base: check out, set up Python 3.13, `python -m pip install --upgrade pip`, `python -m pip install -e ".[dev]"`, run `pytest`, `ruff` and `mypy`. The tests need no display. The file stays in `.gitea/workflows`, not `.github/workflows`, because GitHub refuses a push that touches `.github/workflows` from a token without the workflow scope, which would block the push mirror to GitHub. | No | |
| 7 | Set the repository description and topics | Set the description and at least 5 topics of this repository on the git host with the Gitea application programming interface (API), using `GITEA_TOKEN` from the personal `.env` file; the file is only read by the command, never imported, tested or tracked. Use the proposed text of the Deliverable section once S01 has confirmed it. Serves S03 and objective 10 of the Business Case. | No | |
---
[BC-001]: ../business-case.md
[PP-001]: ../project-plan.md
[020-snake-game]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/020-snake-game
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
+94
View File
@@ -0,0 +1,94 @@
# MIL-002: Adopt the game
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-002 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version, reviewed in RC-005 (Go) | [f13d004] |
---
## Purpose
This gate decides whether the finished game of the base ([020-snake-game], `main`) runs in this repository: the snake, the food, the scoreboard, the main flow and all their tests are here, they pass, and the game can be played. It does not yet compare the game with the day-21 lectures; that is [MIL-003]. The work is delivered on the branch `mil-002-adopt-the-game` and one pull request.
## Deliverable
`src/snake_game/snake.py` (the class `Snake`), `src/snake_game/food.py` (the class `Food`), `src/snake_game/scoreboard.py` (the class `Scoreboard`), `src/snake_game/main.py` and `src/snake_game/__main__.py` (the main flow and `python -m snake_game`), and the tests `tests/fakes.py`, `tests/test_snake.py`, `tests/test_food.py`, `tests/test_scoreboard.py` and `tests/test_main.py`. Running `python -m snake_game` plays the whole game.
The files are copied from the base and changed only where the identity of this repository requires it. The module split of the base is kept: the lecture's single script is already divided into `Snake`, `Food`, `Scoreboard` and a main flow, and the main flow keeps the lecture's names (`screen`, `snake`, `food`, `scoreboard`, `game_is_on`). The pull request lists every difference from the base.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | The adopted files match the base | The pull request lists every difference between each adopted file and the base, or says that there is none | A difference that the list does not name |
| 2 | All tests pass without a display | `pytest` exits 0; no test opens a window; every test of the base is present | A failing test, or a test of the base is missing |
| 3 | Lint, format and types are clean | `python -m ruff check src tests`, `python -m ruff format --check src tests` and `python -m mypy` exit 0, as in continuous integration (CI) | Any of the three fails |
| 4 | `doxygen Doxyfile` builds | 0 warnings | Any warning |
| 5 | The game can be played | S01 runs `python -m snake_game` in Windows PowerShell: the window opens, the snake moves and turns, food is shown, the snake eats and grows, the score rises, and the game ends at the wall and at the tail | The game does not start, or one of those things does not happen |
| 6 | Closing the window ends quietly | Closing the window during play, and after game over, ends the program with exit code 0 and no traceback | A traceback |
| 7 | Importing the main flow needs no display | Importing `snake_game.main` loads neither `turtle` nor `tkinter` | Either module is loaded by the import |
| 8 | The assignment's names exist | Every name of objective 5 of [BC-001] exists with that spelling | A name is missing or spelled differently |
| 9 | Constants are in one place | No module other than `constants.py` defines a value of the lectures | A value is a literal in another module |
| 10 | The code is reviewed | `RC-*` against `QC-PY-001` has the verdict `Go` | Verdict `No-Go` or `Go-with-conditions` |
| 11 | The README matches the adopted game | The Run section and the Project layout of `README.md` describe the files and the command of this milestone, and no sentence says that the game is still to come | A sentence that is out of date, or a file or command that the README does not name |
| 12 | No secret is in the change | `.env` is not tracked and no token appears in any changed file | A token is found in the diff |
## Dependencies
| Depends on | Reason |
| --- | --- |
| [MIL-001] accepted and merged | The package, `constants.py`, the test set-up, the Doxyfile and the CI workflow exist there |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 1: the day-20 behaviour is kept | [BC-001], criterion 1 in Success Criteria |
| Objectives 2 and 3: food, eating, score and game over | [BC-001], criteria 2 and 3 in Success Criteria |
| Objective 4: inheritance and slicing | [BC-001], criterion 4 in Success Criteria |
| Objective 5: the assignment's names | [BC-001], criterion 9 in Success Criteria |
| Objective 7: tests without a display | [BC-001], criterion 5 in Success Criteria |
| Objective 8: Doxygen and README | [BC-001], criterion 7 in Success Criteria |
| Objective 9: traceable steps; the base is adopted without hidden change | [BC-001], criteria 10 and 12 in Success Criteria |
| Design of `Snake`, `Food`, `Scoreboard` and the main flow: no Design Class Diagram exists in this project and none is wanted for a learning project of this size. The classes trace to the day-21 lectures, to the base and to tasks 2 to 5 below. This is a recorded deviation from `QC-PY-001` criterion 10, as in the base | [PP-001] |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 |
## Target Date
2026-10-12 — second of three gateways, inside the one-week plan of [PP-001] that ends 2026-10-16.
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Adopt the test fakes | Copy `tests/fakes.py` from the base: the fake segment, the fake screen and the fake `Turtle` base class that record their calls, so that every test runs without a display. The fake `turtle` module is installed before `food` and `scoreboard` are imported, because a class that inherits from `Turtle` needs the module at import time. List every difference from the base in the pull request. | No | |
| 2 | Adopt the Snake class and its tests | Copy `src/snake_game/snake.py` and `tests/test_snake.py` from the base: `create_snake`, `add_segment`, `extend`, `move`, `hits_wall`, `hits_tail`, `up`, `down`, `left`, `right`, the `segments` list and the `head`. The tail check loops over the slice `segments[1:]`. `snake.py` does not import `turtle` until a real segment is made, so the tests pass fakes. | No | |
| 3 | Adopt the Food class and its tests | Copy `src/snake_game/food.py` and `tests/test_food.py` from the base: `class Food(Turtle)`, whose `__init__` calls `super().__init__()` and `refresh`, and whose random place comes from one function that the tests replace. The values are checked against the lectures in MIL-003. | No | |
| 4 | Adopt the Scoreboard class and its tests | Copy `src/snake_game/scoreboard.py` and `tests/test_scoreboard.py` from the base: `class Scoreboard(Turtle)` with `update_scoreboard`, `increase_score` and `game_over`. The values are checked against the lectures in MIL-003. | No | |
| 5 | Adopt the main flow and the entry point | Copy `src/snake_game/main.py`, `src/snake_game/__main__.py` and `tests/test_main.py` from the base: the screen set-up, the key bindings, the animation loop with `game_is_on`, the eating check, the game-over check, the wait for a click and the quiet exit when the window is closed. `main` imports `food` and `scoreboard` only when it runs, so importing it needs neither `turtle` nor `tkinter`. | No | |
| 6 | Describe the adopted game in the README | Update the Run section and the Project layout of `README.md` so that they match the files and the command of this milestone (`python -m snake_game`, the modules of `src/snake_game/`, the tests), and remove the sentence that says the game is still to come. MIL-003 finishes the README for the whole game. Serves S02 and S03. | No | |
| 7 | Verify the adopted game end to end | Run `pytest`, `ruff check`, `ruff format --check`, `mypy` and `doxygen Doxyfile` in a fresh `.venv`, run `python -m snake_game` and play it until the game is over, close the window during play, and record the results and the list of differences from the base in the pull request. | No | |
---
[BC-001]: ../business-case.md
[PP-001]: ../project-plan.md
[MIL-001]: ./mil-001-project-foundation.md
[MIL-003]: ./mil-003-check-against-day-21.md
[020-snake-game]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/020-snake-game
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
@@ -0,0 +1,108 @@
# MIL-003: Check against day 21
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-003 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version, reviewed in RC-006 (Go) | [f13d004] |
---
## Purpose
This gate decides whether the adopted game does what the five day-21 lectures say, and whether the repository is finished. The base was written against assumed day-21 numbers; this milestone replaces the assumptions by the values of the lecture summaries, corrects the code where it differs, and finishes the README. It is the last gate of [PP-001]. The work is delivered on the branch `mil-003-check-against-day-21` and one pull request.
## Deliverable
A comparison table in the pull request with one row per lecture point below (value in the lecture summary, value in the code, same or different), the corrections of every difference with tests, a finished `README.md` that describes the whole game and this repository, and a check of the repository page. If nothing differs, the table says so and no source file changes.
The lecture points are the specification of this milestone:
| Lecture | Point of the lecture summary | Where it lives in the code |
| --- | --- | --- |
| 1. Inheritance and slicing | One class inherits the attributes and methods of another; lists are sliced | `class Food(Turtle)`, `class Scoreboard(Turtle)`, `segments[1:]` |
| 2. Detect collisions with food | `Food` inherits from `Turtle`; a blue circle of 10 by 10 pixels | `FOOD_SHAPE`, `FOOD_COLOR`, `FOOD_SIZE` (0.5 of a default turtle) |
| 2. Detect collisions with food | The random place comes from the `random` module and is never at the edge of the screen | `random_coordinate`, `WALL_LIMIT` (280) |
| 2. Detect collisions with food | The snake eats the food when the distance between the head and the food is less than 15 pixels | `FOOD_COLLISION_DISTANCE`, `eat_food_if_close` |
| 2. Detect collisions with food | `refresh` gives the food new random coordinates; it runs when the food is made and at every collision | `Food.refresh`, called from `Food.__init__` and `eat_food_if_close` |
| 3. Scoreboard | `Scoreboard` inherits from `Turtle`; the score starts at 0; the text is written with alignment and font; the turtle is hidden; colour and place are set | `Scoreboard.__init__`, `SCOREBOARD_COLOR`, `SCOREBOARD_POSITION`, `SCOREBOARD_ALIGNMENT`, `SCOREBOARD_FONT` |
| 3. Scoreboard | `increase_score` adds 1; the old text is cleared before the new text is written; `update_scoreboard` does both; alignment and font are constants | `Scoreboard.increase_score`, `Scoreboard.update_scoreboard` |
| 4. Wall | The wall is at 280 and -280 on both axes; passing it stops the game (`game_is_on` becomes false); GAME OVER is shown in the middle with the score still visible | `Snake.hits_wall`, `WALL_LIMIT`, `Scoreboard.game_over`, `GAME_OVER_TEXT`, `GAME_OVER_POSITION` |
| 5. Tail | Eating adds a segment: `extend` calls `add_segment` with the position of the last segment | `Snake.extend`, `Snake.add_segment` |
| 5. Tail | The head touches the tail when it is closer than 10 pixels to a segment; the head is skipped, so it does not collide with itself | `Snake.hits_tail`, `TAIL_COLLISION_DISTANCE`, `segments[1:]` |
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | The comparison is complete | The pull request has one row for every lecture point above, with the value of the lecture summary, the value of the code and the result | A lecture point has no row |
| 2 | Every difference is resolved | Each row marked different is corrected in the code with a test, or S01 accepts it with a reason written in the pull request | A difference stays open |
| 3 | The lessons of day 21 are visible | `Food` and `Scoreboard` are subclasses of `turtle.Turtle` and call `super().__init__()`; `hits_tail` loops over `segments[1:]` | Either class does not inherit from `Turtle`, or the loop includes the head |
| 4 | Food is shown | A manual run shows one small blue circle at a random place inside the wall; a second run shows another place; it is never at the very edge of the screen | No food, not a circle, or outside the wall |
| 5 | The snake eats | When the head comes closer than `FOOD_COLLISION_DISTANCE` the food moves to a new random place, the snake grows by one segment and the score rises by 1; it works again for the next food | Any of the three does not happen, or the score rises without the food being eaten |
| 6 | The scoreboard shows the score | White text `Score: 0` at the top centre; after eating it shows `Score: 1` and the old text is gone | Text overlaps, is missing or is not at the top centre |
| 7 | The wall ends the game | A manual run shows the game ending when the head passes the wall on each of the four sides; GAME OVER is in the middle of the window and the score stays visible | The game goes on beyond the wall, ends inside it, or shows no text |
| 8 | The tail ends the game | Turning the head into the body ends the game; normal movement, including the moves right after eating, does not | The game does not end, or ends without a touch |
| 9 | A click closes the window | After game over a click closes the window and the program ends with exit code 0; closing the window during play also ends with exit code 0 and no traceback | The window stays, or a traceback appears |
| 10 | Tests and checks are green | `pytest` exits 0 with no display; `ruff check`, `ruff format --check` and `mypy` exit 0; `doxygen Doxyfile` ends with 0 warnings | Any check fails |
| 11 | The README is finished | It describes the whole game (moving, food, score, game over, closing) and this repository; it has no placeholder and no sentence that is out of date; a fresh clone reaches a green `pytest` by following it | A placeholder or an out-of-date sentence, or a command fails |
| 12 | The repository page is complete | Description is non-empty and there are at least 5 topics on the git host | Description empty or fewer than 5 topics |
| 13 | The game matches the lecture | S01 compares the finished game with the lecture video and notes any difference in the pull request | An undocumented difference |
| 14 | The code is reviewed | If a source file changed, `RC-*` against `QC-PY-001` has the verdict `Go`; if none changed, the pull request says so | Verdict `No-Go` or `Go-with-conditions` |
## Dependencies
| Depends on | Reason |
| --- | --- |
| [MIL-002] accepted and merged | The game that is checked exists there |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objectives 2 and 3: food, eating, score, game over as the lectures give them | [BC-001], criteria 2 and 3 in Success Criteria |
| Objective 4: inheritance and slicing | [BC-001], criterion 4 in Success Criteria |
| Objective 1: the day-20 behaviour is kept | [BC-001], criterion 1 in Success Criteria |
| Objective 7: tests without a display | [BC-001], criterion 5 in Success Criteria |
| Objective 8: README and Doxygen | [BC-001], criteria 6 and 7 in Success Criteria |
| Objective 9: traceable steps | [BC-001], criterion 10 in Success Criteria |
| Objective 10: repository page | [BC-001], criterion 11 in Success Criteria |
| Design of any corrected class or method: no Design Class Diagram exists; a correction traces to its lecture point in the table above, a recorded deviation from `QC-PY-001` criterion 10 as in [MIL-002] | [PP-001] |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 |
## Target Date
2026-10-14 — last of three gateways, inside the one-week plan of [PP-001] that ends 2026-10-16.
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Check inheritance and slicing against lecture 1 | Compare the code with the lecture on class inheritance and slicing: `Food` and `Scoreboard` are subclasses of `Turtle` that call `super().__init__()`, and the tail check slices the segments so that the head is left out. Write the result as rows of the comparison table in the pull request. | No | |
| 2 | Check the food against the collision lecture | Compare the food with the lecture on collisions with food: a blue circle of 10 by 10 pixels (`FOOD_SIZE` 0.5), a random place from the `random` module that is never at the edge of the screen, `refresh` at creation and at every collision, and the eating distance of less than 15 pixels. Write the result as rows of the comparison table. | No | |
| 3 | Check the scoreboard against its lecture | Compare the scoreboard with the lecture: the score starts at 0, the text is written with alignment and font taken from constants, the turtle is hidden, `increase_score` adds 1, and `update_scoreboard` clears the old text before it writes the new one. Write the result as rows of the comparison table. | No | |
| 4 | Check the wall and the game-over text against their lecture | Compare the wall and the end of the game with the lecture: the wall is at 280 and -280 on both axes, passing it sets `game_is_on` to false, and GAME OVER is shown in the middle with the score still visible. Write the result as rows of the comparison table. | No | |
| 5 | Check growth and the tail against their lecture | Compare `extend`, `add_segment` and the tail check with the lecture: `extend` adds a segment at the position of the last segment, and the head touches the tail below 10 pixels with the head itself skipped. Write the result as rows of the comparison table. | No | |
| 6 | Correct the code where it differs from the lectures | For every row of the comparison table marked different, change the constant or the code, add or change the test that proves it, and say so in the pull request. If no row differs, change no source file and state that in the pull request. | No | |
| 7 | Finish the README for the Day 21 repository | Rewrite the Status and Run sections of `README.md` for the whole game (moving, food, score, game over, closing), remove every sentence that is out of date, update the Project layout, and confirm that `doxygen Doxyfile` ends with 0 warnings and that a fresh clone reaches a green `pytest` by following the README. | No | |
| 8 | Check the repository page and compare with the video | Check on the git host that the description and at least 5 topics are still set, run the finished game next to the lecture video, and write every difference in the pull request. | No | |
---
[BC-001]: ../business-case.md
[PP-001]: ../project-plan.md
[MIL-002]: ./mil-002-adopt-the-game.md
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
+121
View File
@@ -0,0 +1,121 @@
# Project Plan: Snake Game (Day 21)
## Metadata
| Key | Value |
| --- | --- |
| ID | PP-001 |
| CrossReference | [BC-001], [SA-001], [MIL-001], [MIL-002], [MIL-003] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S01 | Initial version, accepted by the Product Owner in chat (no QC checklist exists for the plan) | [f13d004] |
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S01 | Sync applied: milestone links and issue numbers; description and topics set; open issues closed on S01's instruction in chat | [f13d004] |
---
## Purpose
This plan schedules the three milestones that deliver the Snake Game (Day 21) repository of [BC-001] in one phase of about one week. The repository starts from the finished `main` of the day-20 repository [020-snake-game] (commit `1a638c9`), which already holds the game of days 20 and 21 with tests and documentation. The three milestones therefore adopt that base, check it against the day-21 lectures, and finish the repository. Each milestone is one gateway document, one branch and one pull request, so that every step is kept track of and reviewed before the next one starts.
## Planning Assumptions
- The phase starts 2026-10-08 and ends by 2026-10-16, which leaves two days of buffer after [MIL-003]. All dates are proposed and need the Product Owner's confirmation (see Open Issues).
- Phase length: one to three days per milestone, sized for the spare time of S01, who owns every phase ([SA-001]).
- The starting point is the finished base, not the day-20 state. S01 chose this on 2026-10-08, in chat, after being told that the base already holds the day-21 features. The plan therefore does not rebuild the game in lecture order; it splits the work by activity: the foundation files ([MIL-001]), the game and its tests ([MIL-002]), and the check against the lectures ([MIL-003]).
- The base is copied file by file, so each adopted file is a task, and every difference from the base is listed in the pull request.
- One branch per milestone, named after it (`mil-001-project-foundation`, `mil-002-adopt-the-game`, `mil-003-check-against-day-21`), and one pull request that closes the issues of that milestone with one `Closes #N` line each.
- Nothing is committed, pushed or merged until S01 asks; S01 reviews the working tree first.
- The plan gate is enabled for commits in this clone (`core.hooksPath` is `framework/githooks`): a commit that changes `src/` or `tests/` needs a `Task: MIL-NNN#N` trailer for an accepted, reviewed milestone.
## Gateway Schedule
| Gateway | Document | Window | Decision date | Owner | Stories | Main deliverable | Milestone |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Project foundation | [MIL-001] | 2026-10-08 to 2026-10-09 | 2026-10-09 | S01 | None (see Open Issues) | `pyproject.toml`, `.gitignore`, `constants.py`, README, `Doxyfile`, continuous integration (CI) workflow, repository description and topics | [milestone-88] |
| Adopt the game | [MIL-002] | 2026-10-10 to 2026-10-12 | 2026-10-12 | S01 | None (see Open Issues) | `Snake`, `Food`, `Scoreboard`, the main flow and `python -m snake_game`, with their tests and the README for the adopted game | [milestone-89] |
| Check against day 21 | [MIL-003] | 2026-10-13 to 2026-10-14 | 2026-10-14 | S01 | None (see Open Issues) | Comparison with the five day-21 lectures, corrections, finished README | [milestone-90] |
```plantuml
@startgantt
Project starts 2026-10-08
[MIL-001 Project foundation] starts 2026-10-08 and ends 2026-10-09
[MIL-002 Adopt the game] starts 2026-10-10 and ends 2026-10-12
[MIL-003 Check against day 21] starts 2026-10-13 and ends 2026-10-14
[MIL-001 Go/No-Go] happens 2026-10-09
[MIL-002 Go/No-Go] happens 2026-10-12
[MIL-003 Go/No-Go] happens 2026-10-14
[Buffer] starts 2026-10-15 and ends 2026-10-16
@endgantt
```
## Scope Coverage
| Business Case scope item | Gateway |
| --- | --- |
| Adopting the finished game of the base: configuration, constants, workflow | [MIL-001] |
| Adopting the finished game of the base: `Snake`, `Food`, `Scoreboard`, the main flow and the tests | [MIL-002] |
| Day-21 lecture "Inheritance and slicing": `Food` and `Scoreboard` inherit from `Turtle`, the tail is a slice | [MIL-002] (adopted), [MIL-003] (checked) |
| Day-21 lecture "Detect collisions with food": the `Food` class, `refresh`, the eating distance | [MIL-002] (adopted), [MIL-003] (checked) |
| Day-21 lecture "Scoreboard": the `Scoreboard` class, `increase_score`, `update_scoreboard` | [MIL-002] (adopted), [MIL-003] (checked) |
| Day-21 lecture "Wall": the wall at 280 and the game-over text | [MIL-002] (adopted), [MIL-003] (checked) |
| Day-21 lecture "Tail": `extend`, `add_segment` and the tail check | [MIL-002] (adopted), [MIL-003] (checked) |
| Checking each rule against the lecture summaries and correcting the base | [MIL-003] |
| Constants in `constants.py`; `src/`, `tests/`, `docs/` layout | [MIL-001], corrected in [MIL-003] where a value differs |
| `pyproject.toml`, Python `.gitignore`, `Doxyfile`, README, continuous integration workflow | [MIL-001], README updated in [MIL-002] and finished in [MIL-003] |
| Repository description and topics | [MIL-001] (task 7), checked again in [MIL-003] |
## Dependencies
```
MIL-001 → MIL-002 → MIL-003
```
A No-Go on a gateway returns it to S01 for rework and moves every later date by the same number of days; the two buffer days absorb up to two days of slip before the end date 2026-10-16 moves.
## Plan Risks
| Risk | Impact | Mitigation |
| --- | --- | --- |
| The planning documents take longer to review than the work left on the game | The first gateway slips | Review [BC-001], [SA-001], [DICT-001] and this plan together in one sitting; keep the milestones small |
| Author and reviewer are the same person (S01) | A review can miss a defect | Use the Quality Criteria (QC) checklists and the pull request as the second look; recorded in [BC-001] |
| The git host has no Actions runner | The CI workflow is never executed | Run the same commands locally before each pull request; decide later whether a runner is needed |
| Lecture details are only available as the summaries in the request | The game differs from the video | S01 compares the finished game with the video at the [MIL-003] Go/No-Go |
| The base was written against assumed day-21 numbers | [MIL-003] finds differences late | The numbers are listed in the lecture-point table of [MIL-003]; a difference is corrected there with a test |
| The base and this repository hold the same code | A later fix reaches only one of them | Out of scope by decision (see [BC-001]); each pull request lists the differences from the base |
| The sync matches issues by title, so a title used twice overwrites an issue | A task disappears from the board | Every task title is unique across all milestones; check before each `--apply` |
## Open Issues
- **Dates:** the start date, milestone lengths and the end date 2026-10-16 are proposed and not given by the Product Owner; confirm or replace them.
- **Product Owner (PO) language:** the request is written in English, so `en` is recorded in `docs/artifact-registry.md`; the sections of every PO-language document follow it. Confirm, because a later change needs a new review of each document.
- **Stakeholder levels:** the Power and Interest levels of S02 and S03 in [SA-001] are proposals, taken over from the day-20 repository.
- **Starting point (closed by S01 on 2026-10-08):** S01 chose the finished `main` of [020-snake-game] as the base, not the day-20 state and not a rebuild.
- **Repository address:** the request names `https://git.tirsystem.com/Tirsvad-Udemy-100_days_of_code` (underscores), but `origin` of this clone is `https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game` (hyphens). The plan uses the address of `origin`, where the repository exists. Confirm.
- **Repository description and topics (closed by S01 on 2026-10-08):** S01 confirmed the text proposed in the Deliverable of [MIL-001] (a description and twelve topics, the same topics as the day-20 repository). It was set on the Gitea repository on 2026-10-08 with the Gitea API; criterion 9 of [MIL-001] checks it.
- **GitHub copy:** a GitHub copy of this repository exists next to the Gitea one and has no description or topics yet. In the day-20 repository S01 decided that a workflow on the git host sets them, so this project does not touch it. S01 confirmed the description and topics for the Gitea repository only, so the GitHub copy was not changed. Confirm that the same holds here, or add a task.
- **"Python greater than 3.13":** read as Python 3.13 or newer (`requires-python = ">=3.13"`); the machine of S01 has Python 3.13.14, which a strict "greater than 3.13" would exclude. Confirm.
- **README template:** the Product Owner's README template is used. It differs from `framework/templates/README-template.md`, whose section titles `framework/scripts/check-readme.sh` expects; that check is opt-in and stays off.
- **Inheritance and display-free tests:** the day-21 lectures teach `class Food(Turtle)`, but a class that inherits from `Turtle` needs `turtle` (and so `tkinter`) at import time, unlike `Snake`. The base keeps the inheritance and has the tests install a fake `turtle` module before they import the classes, and `main` imports `food` and `scoreboard` only when it runs. Confirm, or ask for composition instead.
- **Food under the snake:** the lecture's `refresh` picks a random place without looking at the snake, and so does the base. Confirm, or ask for a place that is free.
- **High score:** no lecture of day 21 stores a high score; it is out of scope. Confirm.
- **No user story or use case:** the tasks are written as build and check steps, so they are plain technical tasks. If the player's goal (steer the snake) should be modelled, add a Use Case Diagram, a user story and a use case and reference them from the task rows.
- **Governance and traceability matrix:** `GOV` and `TM` do not exist yet. The review process asks for both (sign-off route and the "Last Reviewed" column). Decide whether to create them before the first review record is written.
- **Diagram check:** the Gantt chart above was not rendered because no PlantUML server is configured (`PLANTUML_URL`); render it before the review.
- **Sync:** done on 2026-10-08 with `sync-project.sh --accepted-only --apply`: Milestones 88 to 90 and Issues #1 to #22 exist on the git host (MIL-001: #1 to #7, MIL-002: #8 to #14, MIL-003: #15 to #22). The sync matches issues by title, so every task title must be unique across all milestones; they are. Run the sync again whenever a `## Tasks` table changes. It used `GITEA_TOKEN` from the personal `.env` file, which the project never imports.
---
[BC-001]: ./business-case.md
[SA-001]: ./stakeholder-analysis.md
[DICT-001]: ./dictionary.md
[MIL-001]: ./milestones/mil-001-project-foundation.md
[MIL-002]: ./milestones/mil-002-adopt-the-game.md
[MIL-003]: ./milestones/mil-003-check-against-day-21.md
[020-snake-game]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/020-snake-game
[milestone-88]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/milestone/88
[milestone-89]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/milestone/89
[milestone-90]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/milestone/90
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
+71
View File
@@ -0,0 +1,71 @@
# RC-001: Review of BC-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-001 |
| CrossReference | [BC-001], [QC-BC-001], [QC-LANG-001], [DICT-001], [PP-001], [SA-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | [f13d004] |
---
## Artifact Under Review
- Instance reviewed: [BC-001]
- Checklist used: [QC-BC-001] and, for the language and domain, [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (S01 reads English and knows the IT domain)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | ROI/Cost-Benefit analysis is quantitative, or where qualitative, is explicitly justified | Pass | Cost–Benefit Assessment is qualitative and says why: "this is an unpaid learning project with one participant, so money does not measure either side". |
| 2 | Risks are identified with documented impact and mitigation | Pass | Risks table has 12 rows, each with an Impact and a Mitigation (checked by script: no empty cell); three are specific to this repository (assumed day-21 numbers, drift from the base, token leak). |
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | 12 criteria, each with a Target and a Measure, e.g. criterion 7: `doxygen Doxyfile` ends with 0 warnings; criterion 8: 0 entries in `[project].dependencies`; criterion 9: 100% of the listed names exist. Criterion 4 is measured by a review of `src/`, which is checkable but not numeric. |
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | `### In Scope` and `### Out of Scope` subsections; Out of Scope names rebuilding the game and keeping the two repositories in step. |
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | Stakeholders table cites S01, S02 and S03 and states interests only; roles are not re-described. |
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Methodological and Standards Foundation names the framework, Larman, ISO/IEC 25010:2023, PEP 8/257/484, Doxygen and pytest. |
| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Assumptions and Constraints are separate sections; the base being correct is an assumption, the plan window and the plan gate are constraints. |
| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Recommendation: "Proceed — ...", one sentence. |
## 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` is `en` and `Domain` is `it` in the Metadata table. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code; `it` is in the registry's domain list; `check-languages.sh --list` shows `en` and `it` for this document. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. Titles of lectures are quoted in English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register is IT Executive English: short prose; code names and commands appear in backticks only where an objective or a measure needs them. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | Terms are those of [DICT-001] (screen, window, snake, segment, head, body, tail, move, direction, reversal, arrow key, food, refresh, eat, grow, score, scoreboard, wall, touch, game over, inheritance). Searched for the variants collision, collide, heading, boundary, border, apple, fruit, pellet, points, tile and step outside backticks. 'collisions' appears only in the quoted titles of the lectures; 'heading' (a section title) and 'collide' (for eat) were reworded and 'not at its edge' was changed before this review; 'edge of the screen' is the lecture's own phrase for the screen, not a second word for the wall; 'step' only means a project step, as the dictionary rules say. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `docs/` holds one file per artifact; there is no `<name>.<language>.md`. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | N-A | First version; there is 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 | S01 (Product Owner and developer) reads English and knows the IT domain, and asked for this review in chat on 2026-10-08. The terms were also checked against [DICT-001] by the reviewing assistant; S01's own reading is an action item below. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Software Quality Assurance (SQA), Quality Criteria (QC), continuous integration (CI), Python Enhancement Proposals (PEP) and Python Package Index (PyPI) are spelled out on first use. ISO/IEC and UML appear only as the name of a standard and in the title of Larman's book. |
## Overall Verdict
Go — all Mandatory criteria pass. The checklist rows above were transcribed and assessed on 2026-10-08 by the assistant that drafted the documents, at S01's request in chat ("review them and start MIL-001"). S01 is named as reviewer and approves. This review is **not independent**: the drafter and the reviewer are the same assistant, and author and reviewer (S01) are one person in a single-person project (risk recorded in [BC-001] and [PP-001]). S01 has not yet read the document line by line and can overrule this verdict at the pull request.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Read BC-001 and confirm or overrule this `Go` before the pull request of MIL-001 is merged | S01 | 2026-10-09 |
| Decide whether to create the governance document (`GOV`) and the traceability matrix (`TM`); no `TM` row could be added for this review because neither exists (open issue in [PP-001]) | S01 | 2026-10-09 |
---
[BC-001]: ../../business-case.md
[QC-BC-001]: ../../../framework/qc/qc-business-case.md
[QC-LANG-001]: ../../../framework/qc/qc-language-domain.md
[DICT-001]: ../../dictionary.md
[PP-001]: ../../project-plan.md
[SA-001]: ../../stakeholder-analysis.md
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
@@ -0,0 +1,71 @@
# RC-002: Review of SA-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-002 |
| CrossReference | [SA-001], [QC-SA-001], [QC-LANG-001], [BC-001], [DICT-001], [PP-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | [f13d004] |
---
## Artifact Under Review
- Instance reviewed: [SA-001]
- Checklist used: [QC-SA-001] and, for the language and domain, [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (S01 reads English and knows the IT domain)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Power/Interest grid is filled for every stakeholder, with no gaps or unclassified entries | Pass | S01, S02 and S03 each have a Power Level, an Interest Level and a Quadrant. |
| 2 | Each stakeholder is assigned a unique, stable ID (e.g. S01-S11 style) reusable for RACI assignments in other artifacts | Pass | S01 to S03; the milestones and review records use them as owner and reviewer. |
| 3 | Roles and organizational context are defined with explicit Power and Interest levels, not just narrative description | Pass | Role, Organization, Power and Interest are table columns. The levels of S02 and S03 were not stated by the Product Owner; the Purpose says they are proposals, and the Project Plan lists them as an open issue. |
| 4 | Communication needs (channel, frequency, deliverable type) are mapped to project phases or milestones | Pass | Communication Requirements table maps S01, S02 and S03 to channel, frequency, deliverable and the milestones MIL-001 and MIL-003. |
| 5 | Conflicting stakeholder interests are identified with documented mitigation or resolution strategies | Pass | Three conflicts, each with a mitigation (lecture style against structure; nothing to install against pytest and Doxygen; author equals reviewer). |
| 6 | Stakeholder concerns are explicitly traced to Business Case objectives | Pass | Business Goal Alignment table; the objective numbers (1, 2 to 4, 5, 6, 7, 8, 9, 10) were checked against the ten objectives of BC-001 and match. |
| 7 | Primary concerns are expressed in both business language and a recognized quality-attribute mapping (e.g. FURPS+) | Pass | The concern column of the summary table is in business language and the FURPS+ table maps eight concerns to an attribute. |
| 8 | Document is understandable and navigable by non-technical stakeholders reviewing their own entry | Pass | Each stakeholder has one row and one rationale bullet in plain language; abbreviations are spelled out. |
## 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` is `en` and `Domain` is `it` in the Metadata table. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code; `it` is in the registry's domain list; `check-languages.sh --list` shows `en` and `it` for this document. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. Titles of lectures are quoted in English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register is IT Professional English: plain sentences, abbreviations spelled out, identifiers in backticks only in the concern table. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | Terms are those of [DICT-001] (game, snake, food, score, wall, tail, game over, arrow keys). The synonym search of the Business Case review was repeated on this document: only 'step' (project step) was found. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `docs/` holds one file per artifact; there is no `<name>.<language>.md`. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | N-A | First version; there is 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 | S01 (Product Owner and developer) reads English and knows the IT domain, and asked for this review in chat on 2026-10-08. The terms were also checked against [DICT-001] by the reviewing assistant; S01's own reading is an action item below. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Quality Criteria (QC), RACI (Responsible, Accountable, Consulted, Informed) and FURPS+ are spelled out on first use. |
## Overall Verdict
Go — all Mandatory criteria pass. The checklist rows above were transcribed and assessed on 2026-10-08 by the assistant that drafted the documents, at S01's request in chat ("review them and start MIL-001"). S01 is named as reviewer and approves. This review is **not independent**: the drafter and the reviewer are the same assistant, and author and reviewer (S01) are one person in a single-person project (risk recorded in [BC-001] and [PP-001]). S01 has not yet read the document line by line and can overrule this verdict at the pull request.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Read SA-001 and confirm or overrule this `Go`; confirm the proposed Power and Interest levels of S02 and S03 | S01 | 2026-10-09 |
| Decide whether to create the governance document (`GOV`) and the traceability matrix (`TM`); no `TM` row could be added for this review because neither exists (open issue in [PP-001]) | S01 | 2026-10-09 |
---
[SA-001]: ../../stakeholder-analysis.md
[QC-SA-001]: ../../../framework/qc/qc-stakeholder-analysis.md
[QC-LANG-001]: ../../../framework/qc/qc-language-domain.md
[BC-001]: ../../business-case.md
[DICT-001]: ../../dictionary.md
[PP-001]: ../../project-plan.md
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
+68
View File
@@ -0,0 +1,68 @@
# RC-003: Review of DICT-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-003 |
| CrossReference | [DICT-001], [QC-DICT-001], [QC-LANG-001], [BC-001], [PP-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | [f13d004] |
---
## Artifact Under Review
- Instance reviewed: [DICT-001]
- Checklist used: [QC-DICT-001] and, for the language and domain, [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (S01 reads English and knows the IT domain)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Every row has a PO term, its language, an IT term and a definition | Pass | 26 rows; a script found no empty cell. |
| 2 | Each PO term maps to exactly one IT term and the reverse (no synonyms) | Pass | A script found no PO term and no IT term twice. `Turtle` (segment) and 'subclass of `Turtle`' (inheritance) are different IT terms. |
| 3 | Every Domain Model concept has a row, and the Domain Model uses its PO term | N-A | No Domain Model exists in this project (the Dictionary's Rules section says so). |
| 4 | The Operation Contracts, Sequence Diagrams, Design Class Diagrams and ERD use the IT term, not the PO term | N-A | None of these artifacts exists in this project. |
| 5 | Definitions are written in the PO language and are one sentence | Pass | All definitions are English; a script found no definition with a second sentence. |
| 6 | "Used as PO term in" and "Used as IT term in" name artifact types that exist in the project | Pass | The columns name BC, SA, PP and MIL (all exist) and PY, the source-code type of the catalog. |
| 7 | The dictionary's `Language` and `Domain` rows, and the language of every row, match the PO language and domain in the project registry | Pass | Metadata `en` / `it` equals the registry's `PO language` and `PO domain`; the Language column of every row is `en`. |
## 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` is `en` and `Domain` is `it` in the Metadata table. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code; `it` is in the registry's domain list; `check-languages.sh --list` shows `en` and `it` for this document. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. Titles of lectures are quoted in English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register is IT Professional English: one-sentence definitions with the IT term in backticks. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The document is the dictionary: its PO terms are its own rows. A script found no term twice. The two rules about 'step' and 'base' keep two project words out of the game vocabulary. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `docs/` holds one file per artifact; there is no `<name>.<language>.md`. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | N-A | First version; there is 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 | S01 (Product Owner and developer) reads English and knows the IT domain, and asked for this review in chat on 2026-10-08. The terms were also checked against [DICT-001] by the reviewing assistant; S01's own reading is an action item below. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Product Owner (PO) and information technology (IT) are spelled out on first use; the artifact short names in the last two columns are the catalog's. |
## Overall Verdict
Go — all Mandatory criteria pass (criteria 3 and 4 are N-A because the Domain Model and the design artifacts do not exist in this project). The checklist rows above were transcribed and assessed on 2026-10-08 by the assistant that drafted the documents, at S01's request in chat ("review them and start MIL-001"). S01 is named as reviewer and approves. This review is **not independent**: the drafter and the reviewer are the same assistant, and author and reviewer (S01) are one person in a single-person project (risk recorded in [BC-001] and [PP-001]). S01 has not yet read the document line by line and can overrule this verdict at the pull request.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Read DICT-001 and confirm or overrule this `Go` | S01 | 2026-10-09 |
---
[DICT-001]: ../../dictionary.md
[QC-DICT-001]: ../../../framework/qc/qc-dictionary.md
[QC-LANG-001]: ../../../framework/qc/qc-language-domain.md
[BC-001]: ../../business-case.md
[PP-001]: ../../project-plan.md
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
+71
View File
@@ -0,0 +1,71 @@
# RC-004: Review of MIL-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-004 |
| CrossReference | [MIL-001], [QC-MIL-001], [QC-LANG-001], [BC-001], [DICT-001], [PP-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | [f13d004] |
---
## Artifact Under Review
- Instance reviewed: [MIL-001]
- Checklist used: [QC-MIL-001] and, for the language and domain, [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (S01 reads English and knows the IT domain)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section lists the files of the foundation and the repository page; the proposed description and topics are written out. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Twelve Go/No-Go rows, each with a command or an observable result (for example `git check-ignore .venv .env __pycache__` lists all three). |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table: PP-001 accepted, and this milestone accepted with a Go review (plan-first gate). |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to BC-001 objectives 6, 7, 8, 9 and 10 and Success Criteria 5 to 8, 10, 11 and 12; the numbers were checked against BC-001. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table: Owner S01, Approving reviewer S01 (same person; see verdict). |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-10-09; BC-001 Constraints give a plan window ending 2026-10-16. |
## 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` is `en` and `Domain` is `it` in the Metadata table. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code; `it` is in the registry's domain list; `check-languages.sh --list` shows `en` and `it` for this document. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. Titles of lectures are quoted in English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register is IT Executive English: short prose; code names and commands appear in backticks only where a task or a check needs them. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | Terms are those of [DICT-001]. The synonym search found 'heading' (reworded to 'section title' before this review) and none else; the Go/No-Go table names commands because its criteria must be objectively checkable. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `docs/` holds one file per artifact; there is no `<name>.<language>.md`. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | N-A | First version; there is 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 | S01 (Product Owner and developer) reads English and knows the IT domain, and asked for this review in chat on 2026-10-08. The terms were also checked against [DICT-001] by the reviewing assistant; S01's own reading is an action item below. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Continuous integration (CI) and application programming interface (API) are spelled out on first use; HTML and URL are not expanded. |
## Overall Verdict
Go — all Mandatory criteria pass. The checklist rows above were transcribed and assessed on 2026-10-08 by the assistant that drafted the documents, at S01's request in chat ("review them and start MIL-001"). S01 is named as reviewer and approves. This review is **not independent**: the drafter and the reviewer are the same assistant, and author and reviewer (S01) are one person in a single-person project (risk recorded in [BC-001] and [PP-001]). S01 has not yet read the document line by line and can overrule this verdict at the pull request.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Read MIL-001 and confirm or overrule this `Go` before the pull request of MIL-001 is merged | S01 | 2026-10-09 |
| Confirm the proposed repository description and topics in the Deliverable section before task 7 sets them (done: S01 confirmed in chat and task 7 was carried out on 2026-10-08) | S01 | 2026-10-09 |
| Confirm or overrule the code review RC-007 (`QC-PY-001`, verdict Go, written on 2026-10-08) before the pull request (Go/No-Go criterion 11) | S01 | 2026-10-09 |
| Decide whether to create the governance document (`GOV`) and the traceability matrix (`TM`); no `TM` row could be added for this review because neither exists (open issue in [PP-001]) | S01 | 2026-10-09 |
---
[MIL-001]: ../../milestones/mil-001-project-foundation.md
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/qc-language-domain.md
[BC-001]: ../../business-case.md
[DICT-001]: ../../dictionary.md
[PP-001]: ../../project-plan.md
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
+70
View File
@@ -0,0 +1,70 @@
# RC-005: Review of MIL-002
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-005 |
| CrossReference | [MIL-002], [QC-MIL-001], [QC-LANG-001], [BC-001], [DICT-001], [PP-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | [f13d004] |
---
## Artifact Under Review
- Instance reviewed: [MIL-002]
- Checklist used: [QC-MIL-001] and, for the language and domain, [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (S01 reads English and knows the IT domain)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section lists every source and test file of the game and the command that plays it. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Twelve Go/No-Go rows, each with a command or an observable result. The review found no criterion for the README, which would be out of date after the merge; criterion 11 and task 6 were added before this record. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table: MIL-001 accepted and merged, which provides the package, the constants, the test set-up, the Doxyfile and the CI workflow. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to BC-001 objectives 1 to 5, 7, 8 and 9 and Success Criteria 1 to 5, 7, 9, 10 and 12, and records the deviation from `QC-PY-001` criterion 10 (no Design Class Diagram). |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table: Owner S01, Approving reviewer S01 (same person; see verdict). |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-10-12; BC-001 Constraints give a plan window ending 2026-10-16. |
## 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` is `en` and `Domain` is `it` in the Metadata table. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code; `it` is in the registry's domain list; `check-languages.sh --list` shows `en` and `it` for this document. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. Titles of lectures are quoted in English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register is IT Executive English: short prose; code names and commands appear in backticks only where a task or a check needs them. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | Terms are those of [DICT-001]. The synonym search found none outside backticks and quoted lecture titles. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `docs/` holds one file per artifact; there is no `<name>.<language>.md`. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | N-A | First version; there is 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 | S01 (Product Owner and developer) reads English and knows the IT domain, and asked for this review in chat on 2026-10-08. The terms were also checked against [DICT-001] by the reviewing assistant; S01's own reading is an action item below. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Continuous integration (CI) is spelled out on first use (fixed before this review). |
## Overall Verdict
Go — all Mandatory criteria pass. The checklist rows above were transcribed and assessed on 2026-10-08 by the assistant that drafted the documents, at S01's request in chat ("review them and start MIL-001"). S01 is named as reviewer and approves. This review is **not independent**: the drafter and the reviewer are the same assistant, and author and reviewer (S01) are one person in a single-person project (risk recorded in [BC-001] and [PP-001]). S01 has not yet read the document line by line and can overrule this verdict at the pull request.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Read MIL-002 and confirm or overrule this `Go` before the pull request of MIL-002 is merged | S01 | 2026-10-12 |
| Review the MIL-002 code against `QC-PY-001` and record the result as a separate `RC-*` before the pull request (Go/No-Go criterion 10) | S01 | 2026-10-12 |
| Decide whether to create the governance document (`GOV`) and the traceability matrix (`TM`); no `TM` row could be added for this review because neither exists (open issue in [PP-001]) | S01 | 2026-10-12 |
---
[MIL-002]: ../../milestones/mil-002-adopt-the-game.md
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/qc-language-domain.md
[BC-001]: ../../business-case.md
[DICT-001]: ../../dictionary.md
[PP-001]: ../../project-plan.md
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
+70
View File
@@ -0,0 +1,70 @@
# RC-006: Review of MIL-003
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-006 |
| CrossReference | [MIL-003], [QC-MIL-001], [QC-LANG-001], [BC-001], [DICT-001], [PP-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | [f13d004] |
---
## Artifact Under Review
- Instance reviewed: [MIL-003]
- Checklist used: [QC-MIL-001] and, for the language and domain, [QC-LANG-001]
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (S01 reads English and knows the IT domain)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section defines the comparison table and lists the ten lecture points that are its specification, each with the place in the code. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Fourteen Go/No-Go rows, each with a command or an observable result; the comparison with the video (criterion 13) is checkable because an undocumented difference is the No-Go. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table: MIL-002 accepted and merged, because the game that is checked exists there. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to BC-001 objectives 1, 2, 3, 4, 7, 8, 9 and 10 and Success Criteria 1 to 7, 10 and 11, and records the deviation from `QC-PY-001` criterion 10. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table: Owner S01, Approving reviewer S01 (same person; see verdict). |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-10-14; BC-001 Constraints give a plan window ending 2026-10-16, which leaves two buffer days. |
## 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` is `en` and `Domain` is `it` in the Metadata table. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code; `it` is in the registry's domain list; `check-languages.sh --list` shows `en` and `it` for this document. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English. Titles of lectures are quoted in English. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register is IT Executive English: short prose; code names appear in backticks in the lecture-point table because each point must point at the code. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | Terms are those of [DICT-001]. 'collide' was changed to the dictionary term 'eats' before this review; 'collisions' remains only in the titles of the lectures, which are quoted. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | `docs/` holds one file per artifact; there is no `<name>.<language>.md`. |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | N-A | First version; there is 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 | S01 (Product Owner and developer) reads English and knows the IT domain, and asked for this review in chat on 2026-10-08. The terms were also checked against [DICT-001] by the reviewing assistant; S01's own reading is an action item below. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | No abbreviation is used that the Business Case does not spell out; the document uses none beyond S01 and the artifact IDs. |
## Overall Verdict
Go — all Mandatory criteria pass. The checklist rows above were transcribed and assessed on 2026-10-08 by the assistant that drafted the documents, at S01's request in chat ("review them and start MIL-001"). S01 is named as reviewer and approves. This review is **not independent**: the drafter and the reviewer are the same assistant, and author and reviewer (S01) are one person in a single-person project (risk recorded in [BC-001] and [PP-001]). S01 has not yet read the document line by line and can overrule this verdict at the pull request.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Read MIL-003 and confirm or overrule this `Go` before the pull request of MIL-003 is merged | S01 | 2026-10-14 |
| Supply the lecture video (or its transcript) that the comparison in criterion 13 needs; the request holds only summaries | S01 | 2026-10-14 |
| Decide whether to create the governance document (`GOV`) and the traceability matrix (`TM`); no `TM` row could be added for this review because neither exists (open issue in [PP-001]) | S01 | 2026-10-14 |
---
[MIL-003]: ../../milestones/mil-003-check-against-day-21.md
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/qc-language-domain.md
[BC-001]: ../../business-case.md
[DICT-001]: ../../dictionary.md
[PP-001]: ../../project-plan.md
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
+59
View File
@@ -0,0 +1,59 @@
# RC-007: Review of the MIL-001 code
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-007 |
| CrossReference | [MIL-001], [QC-PY-001], [BC-001], [PP-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | [d87029a] |
---
## Artifact Under Review
- Instance reviewed: [MIL-001] task 3 and the code of tasks 1 to 6: `src/snake_game/__init__.py`, `src/snake_game/constants.py` and `tests/test_constants.py` (the Python source of the milestone)
- Checklist used: [QC-PY-001]
- Scope: full review. The non-Python files of the milestone (`pyproject.toml`, `.gitignore`, `Doxyfile`, `README.md`, `.gitea/workflows/ci.yml`) are not Python source; the Go/No-Go criteria of [MIL-001] check them.
- Language and domain: n/a (technical type)
- Language reviewer: none
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) | Pass | Package `snake_game`, module `constants`, constants in `UPPER_SNAKE`, test functions in `snake_case`; the ruff rule set includes the `N` (pep8-naming) rules and passes. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes | Pass | Constants carry the dictionary terms (`MOVE_DISTANCE`, `WALL_LIMIT`, `FOOD_COLLISION_DISTANCE`, `GAME_OVER_TEXT`). The only short names are `x`, `y`, `left` and `right` inside one-line comprehensions and unpackings of the tests. |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions | Pass | `ruff format --check src tests` reports 3 files already formatted; `ruff check src tests` reports all checks passed (rules E, F, W, I, N, UP, B, SIM); a search found no `noqa` and no `type: ignore`. |
| 4 | Every function and method signature is type-annotated, including `-> None` | Pass | All 21 test functions are annotated `-> None`; every constant is annotated `Final[...]`; `mypy` in strict mode reports no issues in 3 source files. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) | N-A | The files contain no exception handling (a search for `except` found nothing). |
| 6 | No mutable default arguments and no shadowed builtins | Pass | No function has a default argument; no builtin name is used as a name. |
| 7 | Files, locks and connections are managed with context managers | N-A | The files open no file, lock or connection. |
| 8 | Public modules, classes and functions have docstrings that say what, not how | Pass | `__init__.py` and `constants.py` have a module docstring and a Doxygen file comment; every constant has a Doxygen `##` comment; `doxygen Doxyfile` ends with 0 warnings. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output | Pass | No `print` and no logging in the files; the values of `GITEA_TOKEN` and `GITHUB_PAT` occur only in the untracked, ignored `.env` file (searched by value, names only). |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded | N-A | This milestone defines no class or operation, only constants, which trace to the lecture values listed in the Deliverable of [MIL-001]. The classes of the game arrive in MIL-002, which records the deviation (no Design Class Diagram exists). |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network | Pass | `tests/test_constants.py` has 21 tests named for a behaviour (for example `test_wall_is_280_pixels_from_the_centre`); `pytest` ran 21 tests (21 passed, none opens a window); the tests read module constants only, so they share no state and use no network. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment | Pass | `[tool.mypy] strict = true`; `python -m mypy` ends with "Success: no issues found in 3 source files"; the files do not use `Any`. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused | Pass | `dependencies = []`; the `dev` extra declares pytest, ruff and mypy with lower bounds (`>=`), and all three are used by the checks above. They are not pinned to exact versions, which this Optional criterion would ask for; it is accepted for a development-only extra. |
## Overall Verdict
Go — all Mandatory criteria pass or are N-A with a reason (criteria 5, 7 and 10 do not apply to a module of constants). Commands run on 2026-10-08 in a fresh `.venv` in Windows PowerShell: `pytest` (21 passed), `ruff check`, `ruff format --check`, `mypy`, `doxygen Doxyfile` (0 warnings). The files are copies of the base ([020-snake-game]) with identity-only edits (day number in docstrings, description and repository URL in `pyproject.toml`). This review is **not independent**: the assistant that adopted the code also reviewed it, and author and reviewer (S01) are one person in a single-person project (risk recorded in [BC-001] and [PP-001]). S01 can overrule this verdict at the pull request.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Read the MIL-001 code and the list of differences from the base, and confirm or overrule this `Go` before the pull request of MIL-001 is merged | S01 | 2026-10-09 |
---
[MIL-001]: ../../milestones/mil-001-project-foundation.md
[QC-PY-001]: ../../../framework/qc/qc-programming-python.md
[BC-001]: ../../business-case.md
[PP-001]: ../../project-plan.md
[020-snake-game]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/020-snake-game
[d87029a]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/d87029a2e743e3994062cce833674befe46c6c71
+96
View File
@@ -0,0 +1,96 @@
# Stakeholder Analysis: Snake Game (Day 21)
## Metadata
| Key | Value |
| --- | --- |
| ID | SA-001 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version, reviewed in RC-002 (Go) | [f13d004] |
---
## Purpose
This analysis names the people and groups who have a stake in the Snake Game (Day 21) project, a solution to the day-21 assignment of Udemy's *100 Days of Code: The Complete Python Pro Bootcamp*, and classifies each one on a power/interest grid so the project knows how closely to involve them. The stakeholder IDs (`S01` to `S03`) are the IDs every other artifact uses for owners, reviewers and RACI (Responsible, Accountable, Consulted, Informed) assignments. The method is the power/interest grid: the quadrant decides how often and with what deliverable a stakeholder is addressed.
The Product Owner stated S01, S02 and S03, the Power and Interest levels of S01, and the deliverables of S02 and S03. The Power and Interest levels of S02 and S03 were not stated; they are proposed here, as in the day-20 repository, and are open for confirmation by the reviewer.
## Stakeholder Summary Table
| ID | Name | Role/Title | Organization | Power Level | Interest Level | Quadrant | Primary Concern (Business Language) |
| --- | --- | --- | --- | --- | --- | --- | --- |
| S01 | Jens Tirsvad Nielsen | Course participant; Product Owner, developer and reviewer | Tirsvad (personal learning project) | HIGH | HIGH | Manage Closely | A correct, tested and documented solution of the assignment that is worth keeping and showing |
| S02 | Udemy coursists | Fellow course participants who share code and compare solutions | Udemy course community (external) | LOW | HIGH | Keep Informed | Readable, runnable code that uses the assignment's function names, with README instructions to run it |
| S03 | GitHub viewers | Visitors who browse the repository for ideas | Public (external) | LOW | LOW | Monitor | A clear repository description, topics and README, and no runtime dependencies to install |
## Power/Interest Classification Rationale
- **Manage Closely (S01):** S01 decides scope, adopts and checks the code, and reviews every artifact, so power and interest are both high. S01 is author and reviewer of the same documents; no independent reviewer exists in this project (see the conflict table).
- **Keep Informed (S02):** S02 cannot change the scope or accept a deliverable, so power is low. They compare solutions with their own, so interest in the code's readability and in the way to run it is high. They need the code and the README, not a say in the plan.
- **Monitor (S03):** S03 arrive by chance, do not take part and cannot influence the project, so power and interest are low. Their first impression is only the repository page, which is why description, topics and README are checked once.
## Primary Concerns and FURPS+ Mapping
FURPS+ stands for Functionality, Usability, Reliability, Performance, Supportability and the added constraints (design, implementation, interface, physical).
| ID | Concern | FURPS+ attribute |
| --- | --- | --- |
| S01 | The game behaves as the day-21 lectures describe: the snake eats the food and grows, the score rises, and the game ends at the wall or at its own tail | Functionality |
| S01 | The day-20 behaviour is kept: a three-segment snake that moves by itself and turns with the arrow keys, without a reversal | Functionality |
| S01 | Behaviour is proven by tests that run without a display | Reliability |
| S01 | Every step is a branch and a pull request, reviewed before the next | Supportability |
| S02 | The code is readable and keeps the assignment's names (`Food`, `Scoreboard`, `Snake`, `refresh`, `extend`, `add_segment`, `increase_score`, `update_scoreboard`, `game_over`, `create_snake`, `up`, `down`, `left`, `right`, `segments`, `head`, `game_is_on`) | Usability |
| S02 | The README tells how to create the `.venv`, run the game and run the tests on their operating system | Usability |
| S03 | The repository page says what the project is, with description, topics and README | Usability |
| S03 | Nothing must be installed to run the game apart from Python itself | Implementation (constraint) |
## Communication Requirements
| ID | Channel | Frequency | Deliverable | Phase / Milestone |
| --- | --- | --- | --- | --- |
| S01 | Pull request review in the git host | Once per milestone | Pull request with `Closes #N` lines and the review record | Every milestone ([PP-001]) |
| S02 | README in the repository | Once, updated when the game changes | Set-up, run and test instructions per operating system | [MIL-001], completed in [MIL-003] |
| S03 | Repository description, topics and README | Once, updated when the game changes | Description, topics and README overview | [MIL-001], checked in [MIL-003] |
## Conflicting Interests and Mitigations
| Conflict | Stakeholders | Mitigation |
| --- | --- | --- |
| S02 wants plain code in the style of the lecture; S01 wants constants, tests, Doxygen comments and packaging, which add structure | S01, S02 | Keep the lecture's identifiers and flow in `Snake`, `Food`, `Scoreboard` and in the main flow; put the extra structure in separate places (`constants.py`, an injectable segment factory) so the main flow stays readable |
| S03 wants nothing to install; S01 needs pytest and Doxygen | S01, S03 | The project has no runtime dependencies; pytest is an optional `dev` extra and Doxygen is a documentation tool that the README lists as optional |
| S01 is author and reviewer, so a review is not independent | S01 | Use the Quality Criteria (QC) checklists as the objective measure, record every review as an `RC-*`, and treat the pull request as the second look; recorded as a plan risk in [PP-001] |
## Traceability Analysis
### Business Goal Alignment
| Stakeholder | Concern | Business Case objective |
| --- | --- | --- |
| S01 | Game behaves as the day-21 lectures describe | [BC-001] objectives 2, 3 and 4 |
| S01 | Day-20 behaviour is kept | [BC-001] objective 1 |
| S01 | Tests run without a display | [BC-001] objective 7 |
| S01 | Every step is a branch and a pull request | [BC-001] objective 9 |
| S02 | Readable code with the assignment's names | [BC-001] objective 5 |
| S02 | README with run and test instructions | [BC-001] objectives 6 and 8 |
| S03 | Description, topics and README on the repository page | [BC-001] objective 10 |
| S03 | No runtime dependencies | [BC-001] objective 6 |
## Sign-Off
| Stakeholder | Decision | Date |
| --- | --- | --- |
| S01 | Go in RC-002 (not independent; S01 can overrule) | 2026-10-08 |
---
[BC-001]: ./business-case.md
[PP-001]: ./project-plan.md
[MIL-001]: ./milestones/mil-001-project-foundation.md
[MIL-003]: ./milestones/mil-003-check-against-day-21.md
[f13d004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game/commit/f13d004447ceb631cb22c058d68a21b721a3f04c
Submodule
+1
Submodule framework added at ce1f9ddd3c
+54
View File
@@ -0,0 +1,54 @@
[build-system]
requires = ["setuptools>=77"]
build-backend = "setuptools.build_meta"
[project]
name = "snake-game"
version = "0.1.0"
description = "Snake game from Udemy's 100 Days of Code (day 21), built object-oriented with Python turtle graphics: food, score and game over."
readme = "README.md"
requires-python = ">=3.13"
license = "AGPL-3.0-only"
license-files = ["LICENSE"]
authors = [{ name = "Jens Tirsvad Nielsen" }]
keywords = ["snake", "game", "turtle", "udemy", "100-days-of-code"]
classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.13",
"Topic :: Education",
"Topic :: Games/Entertainment",
]
# The game runs on the standard library only (turtle needs tkinter).
dependencies = []
[project.optional-dependencies]
dev = [
"pytest>=8",
"ruff>=0.6",
"mypy>=1.11",
]
[project.urls]
Repository = "https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game"
[tool.setuptools.packages.find]
where = ["src"]
[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src", "tests"]
[tool.ruff]
line-length = 88
target-version = "py313"
src = ["src", "tests"]
extend-exclude = ["framework", "build"]
[tool.ruff.lint]
select = ["E", "F", "W", "I", "N", "UP", "B", "SIM"]
[tool.mypy]
python_version = "3.13"
strict = true
files = ["src", "tests"]
mypy_path = ["src", "tests"]
+13
View File
@@ -0,0 +1,13 @@
## @package snake_game
# @brief Snake game from Udemy's 100 Days of Code (day 21).
#
# @mainpage Snake Game
#
# A snake of three square segments moves across a Python turtle screen by
# itself and is steered with the arrow keys. It eats food, grows and keeps a
# score, and the game is over when the head passes the wall or touches the
# tail. The game uses the standard library only.
#
# The constants of the game are in constants.py.
"""Snake game from Udemy's 100 Days of Code (day 21)."""
+98
View File
@@ -0,0 +1,98 @@
## @file constants.py
# @brief Constants of the snake game.
#
# Every value that the day-20 and day-21 lectures fix lives here, so that no other
# module contains a magic number. The turtle coordinate system has its centre
# at (0, 0); the 600 by 600 screen therefore reaches from -300 to 300 on both
# axes. A direction is a turtle heading in degrees: 0 points right and the
# angle grows counter-clockwise.
"""Constants of the snake game, as fixed by the day-20 and day-21 lectures."""
from typing import Final
## @brief Width of the screen in pixels.
SCREEN_WIDTH: Final[int] = 600
## @brief Height of the screen in pixels.
SCREEN_HEIGHT: Final[int] = 600
## @brief Background colour of the screen.
SCREEN_BACKGROUND_COLOR: Final[str] = "black"
## @brief Title of the game window.
SCREEN_TITLE: Final[str] = "My Snake Game"
## @brief Shape of every segment of the snake.
SEGMENT_SHAPE: Final[str] = "square"
## @brief Colour of every segment of the snake.
SEGMENT_COLOR: Final[str] = "white"
## @brief Where the segments are drawn when the game starts, from head to tail.
#
# The positions lie on one row, 20 pixels apart, which is the width of a
# default turtle square, so the segments touch without overlapping.
STARTING_POSITIONS: Final[tuple[tuple[int, int], ...]] = ((0, 0), (-20, 0), (-40, 0))
## @brief Distance in pixels that the head moves in one move.
MOVE_DISTANCE: Final[int] = 20
## @brief Direction up, as a turtle heading in degrees.
UP: Final[int] = 90
## @brief Direction down, as a turtle heading in degrees.
DOWN: Final[int] = 270
## @brief Direction left, as a turtle heading in degrees.
LEFT: Final[int] = 180
## @brief Direction right, as a turtle heading in degrees.
RIGHT: Final[int] = 0
## @brief Wait in seconds between two moves.
REFRESH_DELAY_SECONDS: Final[float] = 0.1
## @brief Shape of the food.
FOOD_SHAPE: Final[str] = "circle"
## @brief Stretch factor of the food in both directions; 0.5 is half a default turtle.
FOOD_SIZE: Final[float] = 0.5
## @brief Colour of the food.
FOOD_COLOR: Final[str] = "blue"
## @brief Speed of the food; `fastest` switches its animation off.
FOOD_SPEED: Final[str] = "fastest"
## @brief How far from the centre the wall is, on every side, in pixels.
#
# The head must stay inside it, and the food is shown inside it.
WALL_LIMIT: Final[int] = 280
## @brief The snake eats the food when the head is closer to it than this, in pixels.
FOOD_COLLISION_DISTANCE: Final[int] = 15
## @brief Text in front of the score on the scoreboard.
SCORE_LABEL: Final[str] = "Score: "
## @brief Colour of the scoreboard text.
SCOREBOARD_COLOR: Final[str] = "white"
## @brief Where the scoreboard text is written: the top centre of the screen.
SCOREBOARD_POSITION: Final[tuple[int, int]] = (0, 270)
## @brief Alignment of the scoreboard text around its position.
SCOREBOARD_ALIGNMENT: Final[str] = "center"
## @brief Font of the scoreboard text: family, size and style.
SCOREBOARD_FONT: Final[tuple[str, int, str]] = ("Arial", 24, "normal")
## @brief The head touches the tail when it is closer to a segment than this, in pixels.
TAIL_COLLISION_DISTANCE: Final[int] = 10
## @brief Text shown when the game is over.
GAME_OVER_TEXT: Final[str] = "GAME OVER"
## @brief Where the game-over text is written: the centre of the screen.
GAME_OVER_POSITION: Final[tuple[int, int]] = (0, 0)
+127
View File
@@ -0,0 +1,127 @@
"""Tests of the constants that the day-20 and day-21 lectures fix."""
from snake_game import constants
HALF_WIDTH = constants.SCREEN_WIDTH / 2
HALF_HEIGHT = constants.SCREEN_HEIGHT / 2
def test_screen_size_matches_lecture() -> None:
assert (constants.SCREEN_WIDTH, constants.SCREEN_HEIGHT) == (600, 600)
def test_screen_is_black_and_titled_as_in_the_lecture() -> None:
assert constants.SCREEN_BACKGROUND_COLOR == "black"
assert constants.SCREEN_TITLE == "My Snake Game"
def test_segments_are_white_squares() -> None:
assert constants.SEGMENT_SHAPE == "square"
assert constants.SEGMENT_COLOR == "white"
def test_snake_starts_with_three_segments_at_the_lecture_positions() -> None:
assert constants.STARTING_POSITIONS == ((0, 0), (-20, 0), (-40, 0))
def test_starting_positions_are_distinct_on_one_row() -> None:
positions = constants.STARTING_POSITIONS
assert len(set(positions)) == len(positions)
assert len({y for _, y in positions}) == 1
def test_starting_positions_run_from_head_to_tail_leftwards() -> None:
x_values = [x for x, _ in constants.STARTING_POSITIONS]
assert x_values == sorted(x_values, reverse=True)
def test_starting_positions_are_one_move_distance_apart() -> None:
x_values = [x for x, _ in constants.STARTING_POSITIONS]
gaps = {left - right for left, right in zip(x_values, x_values[1:], strict=False)}
assert gaps == {constants.MOVE_DISTANCE}
def test_starting_positions_are_inside_the_screen() -> None:
assert all(
abs(x) < HALF_WIDTH and abs(y) < HALF_HEIGHT
for x, y in constants.STARTING_POSITIONS
)
def test_move_distance_is_twenty_pixels() -> None:
assert constants.MOVE_DISTANCE == 20
def test_directions_match_the_lecture_headings() -> None:
assert constants.UP == 90
assert constants.DOWN == 270
assert constants.LEFT == 180
assert constants.RIGHT == 0
def test_four_directions_are_distinct() -> None:
directions = (constants.UP, constants.DOWN, constants.LEFT, constants.RIGHT)
assert len(set(directions)) == len(directions)
def test_opposite_directions_differ_by_half_a_turn() -> None:
assert (constants.UP - constants.DOWN) % 360 == 180
assert (constants.LEFT - constants.RIGHT) % 360 == 180
def test_refresh_delay_is_a_tenth_of_a_second() -> None:
assert constants.REFRESH_DELAY_SECONDS == 0.1
def test_food_is_a_small_blue_circle_without_animation() -> None:
assert constants.FOOD_SHAPE == "circle"
assert constants.FOOD_SIZE == 0.5
assert constants.FOOD_COLOR == "blue"
assert constants.FOOD_SPEED == "fastest"
def test_wall_is_inside_the_screen() -> None:
assert 0 < constants.WALL_LIMIT < HALF_WIDTH
assert constants.WALL_LIMIT < HALF_HEIGHT
def test_wall_is_280_pixels_from_the_centre() -> None:
assert constants.WALL_LIMIT == 280
def test_food_is_eaten_closer_than_15_pixels_which_is_less_than_a_move() -> None:
assert constants.FOOD_COLLISION_DISTANCE == 15
assert constants.FOOD_COLLISION_DISTANCE < constants.MOVE_DISTANCE
def test_scoreboard_is_white_text_at_the_top_centre_inside_the_screen() -> None:
x, y = constants.SCOREBOARD_POSITION
assert constants.SCOREBOARD_COLOR == "white"
assert constants.SCOREBOARD_ALIGNMENT == "center"
assert (x, y) == (0, 270)
assert abs(x) < HALF_WIDTH
assert 0 < y < HALF_HEIGHT
def test_scoreboard_text_is_score_label_and_arial_24() -> None:
assert constants.SCORE_LABEL == "Score: "
assert constants.SCOREBOARD_FONT == ("Arial", 24, "normal")
def test_tail_is_touched_closer_than_10_pixels_which_is_less_than_a_move() -> None:
assert constants.TAIL_COLLISION_DISTANCE == 10
assert 0 < constants.TAIL_COLLISION_DISTANCE < constants.MOVE_DISTANCE
def test_game_over_text_is_written_at_the_centre_inside_the_wall() -> None:
x, y = constants.GAME_OVER_POSITION
assert constants.GAME_OVER_TEXT == "GAME OVER"
assert (x, y) == (0, 0)
assert abs(x) < constants.WALL_LIMIT
assert abs(y) < constants.WALL_LIMIT