# Sequence Diagrams: Study Flash Cards ## Metadata | Key | Value | | --- | --- | | ID | SD-001 | | CrossReference | [OC-001], [DCD-001], [DICT-001] | ## 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] | --- ## Sequence: startStudySession **Realizes:** `startStudySession` in [OC-001] ### Diagram ```plantuml @startuml participant ":LevelView" as V participant ":LevelViewModel" as VM V -> VM : choices VM --> V : tuple[Level, ...] @enduml ``` ### Pattern Annotations | Pattern (GRASP / GoF) | Applied to | Rationale | | --- | --- | --- | | MVVM | `LevelView`, `LevelViewModel` | The view shows the choices; the labels and the order are in the view model | ### Postcondition Coverage | Postcondition (from contract) | Satisfied by message | | --- | --- | | The three levels are returned in order | `choices` | | No session or deck is created and no file is read | no other message is sent | ### Responsibility Check The view model owns the choices; the view only draws buttons and forwards the click. ## Sequence: chooseLevel **Realizes:** `chooseLevel` in [OC-001] ### Diagram ```plantuml @startuml participant "main : app" as M participant ":CsvVocabularyRepository" as VR participant ":CsvProgressRepository" as PR participant "level : Level" as L participant ":StudySession" as S participant ":Deck" as D participant ":SpeechPort" as SP M -> VR : load() VR --> M : vocabulary M -> PR : load() PR --> M : deck | None alt deck is None create D M -> D : from_vocabulary(vocabulary) D --> M : deck end M -> L : first(vocabulary.cards) L --> M : level_cards create S M -> S : create(deck, progress, speech, choose, level_cards) M -> S : next_card() activate S S -> D : within(level_cards) D --> S : candidates opt candidates is not empty S -> D : draw(choose, exclude, among=candidates) D --> S : card S -> SP : speak(card.front, front_code) end S --> M : CardDto | None deactivate S @enduml ``` ### Pattern Annotations | Pattern (GRASP / GoF) | Applied to | Rationale | | --- | --- | --- | | Creator | `app.main` creates `StudySession` | It holds the adapters the session needs | | Information Expert | `Level.first`, `Deck.within`, `Deck.draw` | The level knows its limit, the deck knows its cards | | Null Object | `NullSpeech` as `SpeechPort` | The session never tests for speech | ### Postcondition Coverage | Postcondition (from contract) | Satisfied by message | | --- | --- | | A `StudySession` was created and associated with the level | `create(deck, progress, speech, choose, level_cards)` | | A `Deck` was created from the progress file or a copy of the `Vocabulary`, cards outside the level kept | `PR.load()`, `alt` fragment, `from_vocabulary` | | The level's cards are the first N cards of the `Vocabulary` | `first(vocabulary.cards)` | | `current_card` set and a `CardDto` returned, or `None`; the word was passed to the `SpeechPort` | `next_card()` with `within`, the `opt` fragment and `speak` | ### Responsibility Check The composition root only wires; the level selects, the deck holds, the session coordinates; no object receives all messages. ## Sequence: markKnown **Realizes:** `markKnown` in [OC-001] ### Diagram ```plantuml @startuml participant ":FlashCardView" as V participant ":FlashCardViewModel" as VM participant ":StudySession" as S participant ":Deck" as D participant ":CsvProgressRepository" as PR V -> VM : is_known() activate VM VM -> S : mark_known() activate S opt current_card is not None S -> D : remove(card) S -> PR : save(deck) end deactivate S VM -> S : next_card() S --> VM : CardDto | None VM --> V : side, language name, text deactivate VM @enduml ``` ### Pattern Annotations | Pattern (GRASP / GoF) | Applied to | Rationale | | --- | --- | --- | | MVVM | `FlashCardView`, `FlashCardViewModel` | The view raises the event and shows the result; the rule is behind the view model | | Repository | `CsvProgressRepository` | The session stores the deck through a port | ### Postcondition Coverage | Postcondition (from contract) | Satisfied by message | | --- | --- | | The card was removed from the `Deck` | `remove(card)` | | The `Deck` was stored | `save(deck)` | | `current_card` was set to `None` | `mark_known()` ends with no current card; `next_card()` then draws the next | ### Responsibility Check The view model only sequences two session calls and maps the result for the view. ## Sequence: markUnknown **Realizes:** `markUnknown` in [OC-001] ### Diagram ```plantuml @startuml participant ":FlashCardView" as V participant ":FlashCardViewModel" as VM participant ":StudySession" as S participant ":Deck" as D participant ":SpeechPort" as SP V -> VM : next_card() VM -> S : next_card() activate S S -> D : within(level_cards) D --> S : candidates opt candidates is not empty S -> D : draw(choose, exclude=current, among=candidates) D --> S : card S -> SP : speak(card.front, front_code) end S --> VM : CardDto | None deactivate S VM --> V : side, language name, text @enduml ``` ### Pattern Annotations | Pattern (GRASP / GoF) | Applied to | Rationale | | --- | --- | --- | | Information Expert | `Deck.draw` | The deck knows its cards | ### Postcondition Coverage | Postcondition (from contract) | Satisfied by message | | --- | --- | | A different card of the level was chosen when two or more exist | `within(level_cards)`, `draw(choose, exclude=current, among=candidates)` | | Deck and file unchanged | no `remove` or `save` message | | The Malay word was passed to the `SpeechPort` | `speak(card.front, front_code)` | ### Responsibility Check 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