Files
024-snake/docs/milestones/mil-004-high-score-file.md
T
2026-10-13 14:11:53 +08:00

87 lines
5.9 KiB
Markdown

# MIL-004: High score file
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-004 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-13 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version, reviewed in RC-007 (Go) | [e004c34] |
---
## Purpose
This gate decides whether the high score survives between games: it is read from `data.txt` with `with open(...)` when the scoreboard is made, converted from text to an integer, and written back to the file when a new high score is reached. It also decides the behaviour where the lecture is silent: a missing, empty or damaged file. The work is delivered on the branch `mil-004-high-score-file` and one pull request.
## Deliverable
Changed `src/snake_game/scoreboard.py` and `constants.py`, functions that read and write the high score, and tests that use a temporary file. The game, started again after a new high score, shows that high score.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | The high score is read at the start | `Scoreboard()` reads the file named by the constant `HIGH_SCORE_FILE` (`data.txt`) with a `with` statement, converts the text with `int` and shows the value as `High Score` | The value is not read, the file is opened without `with`, or the text is not converted |
| 2 | A new high score is written | When `reset` finds a score above the high score, the file holds the new value as text; a lower or equal score does not write the file | The file is not written, is written for a lower score, or holds something other than the number |
| 3 | A missing file is created | Starting without `data.txt` shows `High Score: 0` and leaves a `data.txt` that holds `0` | A traceback, or no file |
| 4 | A damaged file reads as 0 | An empty file, a file with text that is not a whole number and a negative number all give a high score of 0 without a traceback | A traceback, or a negative high score |
| 5 | The path is a parameter | The file name is a constant used as the default of a parameter, and every test passes a temporary path | A test uses the real `data.txt` |
| 6 | The high score survives a restart | S01 reaches a new high score, closes the window, starts `python -m snake_game` again and sees the same high score | The value is lost |
| 7 | `data.txt` is not tracked | `git check-ignore data.txt` lists it and no `data.txt` is in the change | The file is tracked |
| 8 | Tests, lint, format and types are clean | `pytest`, `python -m ruff check src tests`, `python -m ruff format --check src tests` and `python -m mypy` exit 0, as in continuous integration (CI); no test opens a window | Any of them fails |
| 9 | `doxygen Doxyfile` builds | 0 warnings | Any warning |
| 10 | The code is reviewed | `RC-*` against `QC-PY-001` has the verdict `Go` | Verdict `No-Go` or `Go-with-conditions` |
| 11 | 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-003] accepted and merged | `Scoreboard.reset` and the two scores exist there |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 5: the file read and written with `with` | [BC-001], criterion 4 in Success Criteria |
| Objective 6: a missing or damaged file | [BC-001], criterion 5 in Success Criteria |
| Objective 9: tests never touch the real file | [BC-001], criterion 6 in Success Criteria |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 |
## Target Date
2026-10-21 — fourth of five gateways.
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Add the high score file constant | Add `HIGH_SCORE_FILE: Final[str] = "data.txt"` to `constants.py` with a Doxygen comment, and a test of it. | No | |
| 2 | Read the high score from the file | Add a function that opens the file with `with open(path) as data`, reads it, converts the text with `int` and returns it; `Scoreboard.__init__` takes the path as a parameter with the constant as default and sets `high_score` from it. Tests with a temporary file. | No | |
| 3 | Write the high score to the file | In `Scoreboard.reset`, when a new high score is reached, open the file with `with open(path, mode="w") as data` and write the number as text. Tests check the file content after a higher, equal and lower score. | No | |
| 4 | Handle a missing or damaged file | A missing file is created holding `0`; an empty file, text that is not a whole number or a negative number read as 0 (objective 6 of the Business Case). Tests for each case. | No | |
| 5 | Keep the tests away from the real data.txt | Every test that makes a `Scoreboard` passes a pytest `tmp_path` file; a guard in `tests/conftest.py` fails a test that would open the default path. | No | |
| 6 | Document the high score file in the README | Describe in the Run section where `data.txt` is, that it is created at the first start, how to reset the high score (delete the file) and that it is not tracked by git. Serves S02. | No | |
| 7 | Verify the high score file end to end | Run `pytest`, `ruff check`, `ruff format --check`, `mypy` and `doxygen Doxyfile` in a fresh `.venv`, reach a high score, restart the game, delete and damage `data.txt` and start again, and record the results in the pull request. | No | |
---
[BC-001]: ../business-case.md
[PP-001]: ../project-plan.md
[MIL-003]: ./mil-003-continuous-play-and-high-score.md
[MIL-005]: ./mil-005-wiki-and-finish.md
[021-snake-game]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/021-snake-game
[e004c34]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/024-snake/commit/e004c34565839b38dc1e06c8a05baaa66ce9eb1d