MIL-011 plan and design: menu bar

Milestone MIL-011 with stories US-001.09 to US-001.12, and the documents
updated for the menu bar: BC-001, PP-001, US-001, UC-001, SSD-001, OC-001,
SD-001, DCD-001, DICT-001 and the wireframe. Review records RC-056 to
RC-065, all Go (autonomous mode, not independent).

Task: MIL-011#1
This commit is contained in:
2026-10-15 08:52:13 +08:00
parent 9ab490e520
commit 2211d0f4cb
23 changed files with 1102 additions and 47 deletions
+115 -3
View File
@@ -9,8 +9,8 @@
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added chooseLevel; startStudySession returns the levels | [0b983b7] |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added chooseLevel; startStudySession returns the levels | [0b983b7] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the menu contracts | pending |
---
@@ -93,6 +93,119 @@ The turn-over of the card after 3000 ms is started by the system's own timer, no
| --- | --- |
| `current_card` is `None` (no card is shown) | Nothing is changed and nothing is stored |
## Contract: openWordList
| Item | Value |
| --- | --- |
| Operation | `openWordList(path: Path): tuple[Level, ...]` |
| Traces to | `openWordList` in [SSD-001] |
| Domain Model concepts | Word List, Study Session, Words To Learn ([DM-001]); IT terms `Vocabulary`, `StudySession`, `Deck` ([DICT-001]) |
**Preconditions**
- `path` names an existing file.
**Postconditions**
- The `Vocabulary` of `path` is the word list in use and its progress file (`words_to_learn.csv` for `ms-da.csv`, else `words_to_learn_<name>.csv` in the data folder) is the progress in use.
- Any earlier `StudySession` was dropped and the levels are returned; no card is shown until a level is chosen.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| The file does not exist or is not a word list (no header of two language codes, a row that is not two cells, or no card) | `VocabularyNotFoundError` or `VocabularyFormatError` is raised; the earlier word list and session stay in use and no file is changed |
## Contract: changeLevel
| Item | Value |
| --- | --- |
| Operation | `changeLevel(): tuple[Level, ...]` |
| Traces to | `changeLevel` in [SSD-001] |
| Domain Model concepts | Level, Study Session ([DM-001]); IT terms `Level`, `StudySession` ([DICT-001]) |
**Preconditions**
- A word list is in use.
**Postconditions**
- The pending flip timer was cancelled, the `StudySession` was dropped and the levels are returned; the progress file was not changed.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| None | – |
## Contract: resetWordList
| Item | Value |
| --- | --- |
| Operation | `resetWordList(): tuple[Level, ...]` |
| Traces to | `resetWordList` in [SSD-001] |
| Domain Model concepts | Words To Learn, Word List ([DM-001]); IT terms `Deck`, `Vocabulary` ([DICT-001]) |
**Preconditions**
- A word list is in use and the Learner confirmed.
**Postconditions**
- The progress file of the word list in use does not exist; the word list file and the progress files of other word lists are unchanged.
- The `StudySession` was dropped and the levels are returned; the next session starts from a `Deck` of the whole `Vocabulary`.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| The progress file does not exist | Nothing is deleted and no error is raised |
| The progress file cannot be deleted (`OSError`) | The error is logged and shown to the Learner; the earlier session stays |
## Contract: showContact
| Item | Value |
| --- | --- |
| Operation | `showContact(): tuple[str, str, str]` |
| Traces to | `showContact` in [SSD-001] |
| Domain Model concepts | none (author information, outside the domain) |
**Preconditions**
- None.
**Postconditions**
- The name, the title and the link of the author are returned and the link was opened in the web browser.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| No web browser can be started | The failure is logged; nothing else changes |
## Contract: exit
| Item | Value |
| --- | --- |
| Operation | `exit(): None` |
| Traces to | `exit` in [SSD-001] |
| Domain Model concepts | Study Session ([DM-001]); IT term `StudySession` ([DICT-001]) |
**Preconditions**
- None.
**Postconditions**
- The pending flip timer was cancelled, the window was closed and the program ended with exit code 0; the progress file is as it was after the last `markKnown`.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| None | – |
## Contract: markUnknown
| Item | Value |
@@ -124,5 +237,4 @@ The turn-over of the card after 3000 ms is started by the system's own timer, no
[DM-001]: ../domain-model.md
[DICT-001]: ../dictionary.md
[SD-001]: ./sd.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
+88 -3
View File
@@ -9,8 +9,8 @@
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the sequences startStudySession (levels) and chooseLevel (level filter) | [0b983b7] |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the sequences startStudySession (levels) and chooseLevel (level filter) | [0b983b7] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the sequences openWordList and resetWordList | pending |
---
@@ -109,6 +109,92 @@ deactivate S
The composition root only wires; the level selects, the deck holds, the session coordinates; no object receives all messages.
## Sequence: openWordList
**Realizes:** `openWordList` in [OC-001]
### Diagram
```plantuml
@startuml
participant ":MenuView" as V
participant ":Application" as A
participant ":CsvVocabularyRepository" as VR
V -> A : open_word_list(path)
activate A
create VR
A -> VR : create(path)
A -> VR : load()
alt file is a word list
VR --> A : vocabulary
A -> A : drop session, use progress file of path
A --> V : levels
else file is refused
VR --> A : VocabularyError
A --> V : message, earlier list stays
end
deactivate A
@enduml
```
### Pattern Annotations
| Pattern (GRASP / GoF) | Applied to | Rationale |
| --- | --- | --- |
| Controller | `Application` | Receives the menu command and coordinates the repositories and the session |
| Repository | `CsvVocabularyRepository` | The file format stays in the adapter |
### Postcondition Coverage
| Postcondition (from contract) | Satisfied by message |
| --- | --- |
| The vocabulary and the progress file of `path` are in use | `load()`, `use progress file of path` |
| The earlier session was dropped and the levels are returned | `drop session`, `levels` |
| A refused file leaves everything as it was | the `else` branch |
### Responsibility Check
The view forwards the command; the application validates through the repository before it replaces anything.
## Sequence: resetWordList
**Realizes:** `resetWordList` in [OC-001]
### Diagram
```plantuml
@startuml
participant ":MenuView" as V
participant ":Application" as A
participant ":CsvProgressRepository" as PR
V -> A : reset_word_list()
activate A
A -> PR : reset()
PR --> A : done
A -> A : drop session
A --> V : levels
deactivate A
@enduml
```
### Pattern Annotations
| Pattern (GRASP / GoF) | Applied to | Rationale |
| --- | --- | --- |
| Controller | `Application` | Sequences the reset and the return to the level screen |
| Repository | `CsvProgressRepository` | Knows where the progress file is |
### Postcondition Coverage
| Postcondition (from contract) | Satisfied by message |
| --- | --- |
| The progress file of the word list in use does not exist | `reset()` |
| The session was dropped and the levels are returned | `drop session`, `levels` |
### Responsibility Check
The confirmation is asked by the view before `reset_word_list` is called; the repository deletes only its own file.
## Sequence: markKnown
**Realizes:** `markKnown` in [OC-001]
@@ -209,5 +295,4 @@ Same as `markKnown`; the session is the only object that speaks and draws.
[OC-001]: ./oc.md
[DCD-001]: ../dcd.md
[DICT-001]: ../dictionary.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
+16 -3
View File
@@ -11,8 +11,8 @@
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added chooseLevel; startStudySession returns the levels | [0b983b7] |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added chooseLevel; startStudySession returns the levels | [0b983b7] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the menu operations | pending |
---
@@ -36,6 +36,15 @@ L -> S : markKnown()
S --> L : next card (word, language name)
L -> S : markUnknown()
S --> L : next card (word, language name)
L -> S : openWordList(path)
S --> L : levels, or the reason the file is refused
L -> S : changeLevel()
S --> L : levels
L -> S : resetWordList()
S --> L : levels
L -> S : showContact()
S --> L : name, title, link opened
L -> S : exit()
@enduml
```
@@ -48,6 +57,11 @@ S --> L : next card (word, language name)
| 3 | (timer) turn the card over | none | the same card, translation side | 6 |
| 4 | markKnown | none | next card, or "nothing left to learn" | 7, 8, 9 |
| 5 | markUnknown | none | next card, or "nothing left to learn" | 7a, 9 |
| 6 | openWordList | path of a CSV file | the levels, or the reason the file is refused | *a.1 |
| 7 | changeLevel | none | the levels | *a.2 |
| 8 | resetWordList | none (the Learner confirmed) | the levels | *a.3 |
| 9 | showContact | none | the author's name and title; the link is opened | *a.4 |
| 10 | exit | none | none; the program ends | *a.5 |
The turn-over in step 3 is started by the system's own timer, not by a message from the Learner; it is shown as a return without a call, which is the one deviation from "every return answers a message". When the level is given at start (extension 3a of [UC-001]) the Learner's first message is `chooseLevel` and `startStudySession` is not sent.
@@ -64,5 +78,4 @@ The system instance lives for one run of the program. The words to learn are cre
[UC-001]: ./uc.md
[DM-001]: ../domain-model.md
[OC-001]: ./oc.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
+9 -3
View File
@@ -11,8 +11,8 @@
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the choice of level (US-001.06) | [0b983b7] |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the choice of level (US-001.06) | [0b983b7] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the menu commands as an extension (US-001.09 to US-001.12) | pending |
---
@@ -59,6 +59,12 @@
1. The system tells the Learner that there is nothing left to learn at this level, and further answers change nothing.
- 4a. The kept progress or the word list is unreadable:
1. The system reports the problem to the Learner and ends; it does not overwrite the kept progress.
- *a. At any time the Learner uses a menu command:
1. Open a word list: the system asks for a file and checks it; when it is a word list, the system replaces the word list in use and goes on at step 2; when it is not, the system tells the Learner why and keeps the word list in use. When the Learner cancels nothing changes.
2. Change level: the system goes on at step 2 with the word list in use; the kept progress stays.
3. Reset word list: the system asks the Learner to confirm; on yes it removes the kept progress of the word list in use and goes on at step 2, so all its words are to learn again; on no nothing changes.
4. Contact: the system shows the author's name and title and opens the author's LinkedIn page in the web browser.
5. Exit: the system ends the program.
### Special Requirements / Business Rules
@@ -70,6 +76,7 @@
| 6 | The turn-over comes three seconds after the card appears |
| 8 | A word is identified by its Malay and Danish text; the first equal word is removed; known words stay known at every level and words outside the level are kept |
| 4 | The word list names its two languages and holds one word and one translation per card |
| *a | The kept progress of each word list is separate; resetting one word list never changes another word list or the word list itself |
### Open Issues
@@ -83,5 +90,4 @@
[SA-001]: ../stakeholder-analysis.md
[DM-001]: ../domain-model.md
[SSD-001]: ./ssd.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
+24
View File
@@ -60,3 +60,27 @@ The Product Owner gave this screen in the first prompt (the course's target scre
| Front (first 3000 ms) | `card_front.png` | Malay | the Malay word | black |
| Back (after 3000 ms) | `card_back.png` | Danish | the Danish translation | white |
| Finished | `card_front.png` | (empty) | "Nothing left to learn" | black |
## Menu bar and dialogs (all screens)
```text
+----------------------------------------------------------+
| File About | classic menu bar of the window
+----------------------------------------------------------+
File About
+------------------------+ +-----------------------------------------------+
| Open... | | Contact > |
| Change level... | | +-----------------------------------------+|
| Reset word list... | | | Jens Tirsvad Nielsen, Software engineer ||
| ---------------------- | | | (LinkedIn) ||
| Exit | | +-----------------------------------------+|
+------------------------+ +-----------------------------------------------+
```
| Element | Behaviour |
| --- | --- |
| File, Open... | Standard file dialog for `*.csv` (all files allowed), starting in the data folder; a refused file shows an error message with the reason |
| File, Change level... | Replaces the screen by Screen 1 |
| File, Reset word list... | Question "Start `<name>` from the beginning? All words will be to learn again." with Yes and No; Yes replaces the screen by Screen 1 |
| File, Exit | Closes the window |
| About, Contact, the author entry | Opens https://www.linkedin.com/in/tirsvad74 in the web browser |