Skip to content

Commit 6df917d

Browse files
committed
game over screen update
1 parent 65dc6ad commit 6df917d

20 files changed

Lines changed: 1907 additions & 632 deletions

File tree

CLAUDE.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## What This Is
6+
7+
Magic Yeti — a Flutter app for tracking Magic: The Gathering games (life totals, game timer, match history, player stats, commander decks, friends). Supports iOS, Android, Web, and Windows.
8+
9+
## Common Commands
10+
11+
### Run the app (three flavors)
12+
```bash
13+
flutter run --flavor development --target lib/main_development.dart
14+
flutter run --flavor staging --target lib/main_staging.dart
15+
flutter run --flavor production --target lib/main_production.dart
16+
```
17+
18+
### Tests
19+
```bash
20+
flutter test # all tests (root)
21+
flutter test --coverage --test-randomize-ordering-seed random # with coverage
22+
flutter test test/path/to/specific_test.dart # single test file
23+
cd packages/<package_name> && flutter test # package-level tests
24+
```
25+
26+
### Lint
27+
```bash
28+
flutter analyze
29+
```
30+
Uses `very_good_analysis` (strict lint rules from Very Good Ventures).
31+
32+
### Code generation (JSON serialization)
33+
```bash
34+
dart run build_runner build --delete-conflicting-outputs
35+
```
36+
Run this after modifying any model class annotated with `@JsonSerializable`. Generated files are `*.g.dart`.
37+
38+
### Localization
39+
```bash
40+
flutter gen-l10n --arb-dir="lib/l10n/arb"
41+
```
42+
ARB files in `lib/l10n/arb/`. Supported locales: en, es. Access strings via `context.l10n.keyName`.
43+
44+
## Architecture
45+
46+
**Pattern**: BLoC + Repository. Each feature folder (`lib/<feature>/`) contains `bloc/`, `view/`, `widgets/` subdirectories.
47+
48+
**Navigation**: GoRouter (`lib/app/app_router/app_router.dart`).
49+
50+
**AppBloc** (`lib/app/bloc/`) manages top-level app state: authentication status, maintenance mode, force upgrades, onboarding. App states drive routing (unauthenticated → login, authenticated → home, etc.).
51+
52+
**GameBloc** (`lib/game/bloc/`) manages active game state: players, life totals, timer, elimination detection.
53+
54+
## Packages (`packages/`)
55+
56+
| Package | Purpose |
57+
|---|---|
58+
| `player_repository` | Core game logic: player management, game snapshots, elimination. Uses RxDart streams. |
59+
| `firebase_database_repository` | Firestore/Realtime Database persistence for games and player data. |
60+
| `user_repository` | User state streams, coordinates auth + database repos. |
61+
| `scryfall_repository` + `scryfall_bulk_client` | MTG card data from Scryfall API and bulk assets. |
62+
| `api_client` | Generic HTTP client wrapper. |
63+
| `app_ui` | Shared theme, colors, fonts (Teko family), reusable widgets. |
64+
| `form_inputs` | Form validation models using `formz`. |
65+
| `authentication_client` + `firebase_authentication_client` | Abstract auth interface + Firebase impl (Google/Apple/Email). |
66+
| `app_config_repository` | App config (maintenance mode, force upgrades). Has fake impl for testing. |
67+
| `analytics_repository` | Analytics tracking. |
68+
69+
## Key Conventions
70+
71+
- Models use `@JsonSerializable(explicitToJson: true, includeIfNull: false)` with `json_serializable` codegen.
72+
- State classes use `equatable` for value equality.
73+
- Async data flows use `RxDart` `BehaviorSubject` streams in repositories, consumed by BLoCs.
74+
- CI runs via GitHub Actions (`.github/workflows/main.yaml`): semantic PR checks, Flutter build, spell check.

lib/home/home_page.dart

Lines changed: 111 additions & 113 deletions
Large diffs are not rendered by default.

lib/l10n/arb/app_en.arb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,66 @@
582582
"type": "text",
583583
"placeholders": {}
584584
},
585+
"averageGameDurationTitle": "Average\nGame Duration",
586+
"@averageGameDurationTitle": {
587+
"description": "Title for average game duration stat",
588+
"type": "text",
589+
"placeholders": {}
590+
},
591+
"winRateWhenFirstTitle": "Win Rate\nWhen First",
592+
"@winRateWhenFirstTitle": {
593+
"description": "Title for win rate when going first stat",
594+
"type": "text",
595+
"placeholders": {}
596+
},
597+
"bestCommanderTitle": "Best\nCommander",
598+
"@bestCommanderTitle": {
599+
"description": "Title for highest win rate commander stat",
600+
"type": "text",
601+
"placeholders": {}
602+
},
603+
"currentStreakTitle": "Current\nStreak",
604+
"@currentStreakTitle": {
605+
"description": "Title for current win/loss streak stat",
606+
"type": "text",
607+
"placeholders": {}
608+
},
609+
"mostCommonOpponentTitle": "Most Common\nOpponent",
610+
"@mostCommonOpponentTitle": {
611+
"description": "Title for most common opponent stat",
612+
"type": "text",
613+
"placeholders": {}
614+
},
615+
"nemesisTitle": "Nemesis",
616+
"@nemesisTitle": {
617+
"description": "Title for nemesis stat - opponent who beats you most",
618+
"type": "text",
619+
"placeholders": {}
620+
},
621+
"avgCommanderDamageTakenTitle": "Avg Commander\nDamage Taken",
622+
"@avgCommanderDamageTakenTitle": {
623+
"description": "Title for average commander damage taken per game",
624+
"type": "text",
625+
"placeholders": {}
626+
},
627+
"timesKilledByCommanderTitle": "Killed by\nCommander Dmg",
628+
"@timesKilledByCommanderTitle": {
629+
"description": "Title for times eliminated by 21+ commander damage",
630+
"type": "text",
631+
"placeholders": {}
632+
},
633+
"bestColorComboTitle": "Best Color\nCombo",
634+
"@bestColorComboTitle": {
635+
"description": "Title for best win rate by exact color identity combination",
636+
"type": "text",
637+
"placeholders": {}
638+
},
639+
"bestSingleColorTitle": "Best Single\nColor",
640+
"@bestSingleColorTitle": {
641+
"description": "Title for best win rate by individual color",
642+
"type": "text",
643+
"placeholders": {}
644+
},
585645
"underConstructionText": "Under Construction",
586646
"@underConstructionText": {
587647
"description": "Text shown for features under construction",

lib/l10n/arb/app_localizations.dart

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,66 @@ abstract class AppLocalizations {
644644
/// **'Most Played\nCommander'**
645645
String get mostPlayedCommanderTitle;
646646

647+
/// Title for average game duration stat
648+
///
649+
/// In en, this message translates to:
650+
/// **'Average\nGame Duration'**
651+
String get averageGameDurationTitle;
652+
653+
/// Title for win rate when going first stat
654+
///
655+
/// In en, this message translates to:
656+
/// **'Win Rate\nWhen First'**
657+
String get winRateWhenFirstTitle;
658+
659+
/// Title for highest win rate commander stat
660+
///
661+
/// In en, this message translates to:
662+
/// **'Best\nCommander'**
663+
String get bestCommanderTitle;
664+
665+
/// Title for current win/loss streak stat
666+
///
667+
/// In en, this message translates to:
668+
/// **'Current\nStreak'**
669+
String get currentStreakTitle;
670+
671+
/// Title for most common opponent stat
672+
///
673+
/// In en, this message translates to:
674+
/// **'Most Common\nOpponent'**
675+
String get mostCommonOpponentTitle;
676+
677+
/// Title for nemesis stat - opponent who beats you most
678+
///
679+
/// In en, this message translates to:
680+
/// **'Nemesis'**
681+
String get nemesisTitle;
682+
683+
/// Title for average commander damage taken per game
684+
///
685+
/// In en, this message translates to:
686+
/// **'Avg Commander\nDamage Taken'**
687+
String get avgCommanderDamageTakenTitle;
688+
689+
/// Title for times eliminated by 21+ commander damage
690+
///
691+
/// In en, this message translates to:
692+
/// **'Killed by\nCommander Dmg'**
693+
String get timesKilledByCommanderTitle;
694+
695+
/// Title for best win rate by exact color identity combination
696+
///
697+
/// In en, this message translates to:
698+
/// **'Best Color\nCombo'**
699+
String get bestColorComboTitle;
700+
701+
/// Title for best win rate by individual color
702+
///
703+
/// In en, this message translates to:
704+
/// **'Best Single\nColor'**
705+
String get bestSingleColorTitle;
706+
647707
/// Text shown for features under construction
648708
///
649709
/// In en, this message translates to:

lib/l10n/arb/app_localizations_en.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,36 @@ class AppLocalizationsEn extends AppLocalizations {
301301
@override
302302
String get mostPlayedCommanderTitle => 'Most Played\nCommander';
303303

304+
@override
305+
String get averageGameDurationTitle => 'Average\nGame Duration';
306+
307+
@override
308+
String get winRateWhenFirstTitle => 'Win Rate\nWhen First';
309+
310+
@override
311+
String get bestCommanderTitle => 'Best\nCommander';
312+
313+
@override
314+
String get currentStreakTitle => 'Current\nStreak';
315+
316+
@override
317+
String get mostCommonOpponentTitle => 'Most Common\nOpponent';
318+
319+
@override
320+
String get nemesisTitle => 'Nemesis';
321+
322+
@override
323+
String get avgCommanderDamageTakenTitle => 'Avg Commander\nDamage Taken';
324+
325+
@override
326+
String get timesKilledByCommanderTitle => 'Killed by\nCommander Dmg';
327+
328+
@override
329+
String get bestColorComboTitle => 'Best Color\nCombo';
330+
331+
@override
332+
String get bestSingleColorTitle => 'Best Single\nColor';
333+
304334
@override
305335
String get underConstructionText => 'Under Construction';
306336

lib/l10n/arb/app_localizations_es.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,36 @@ class AppLocalizationsEs extends AppLocalizations {
303303
@override
304304
String get mostPlayedCommanderTitle => 'Most Played\nCommander';
305305

306+
@override
307+
String get averageGameDurationTitle => 'Average\nGame Duration';
308+
309+
@override
310+
String get winRateWhenFirstTitle => 'Win Rate\nWhen First';
311+
312+
@override
313+
String get bestCommanderTitle => 'Best\nCommander';
314+
315+
@override
316+
String get currentStreakTitle => 'Current\nStreak';
317+
318+
@override
319+
String get mostCommonOpponentTitle => 'Most Common\nOpponent';
320+
321+
@override
322+
String get nemesisTitle => 'Nemesis';
323+
324+
@override
325+
String get avgCommanderDamageTakenTitle => 'Avg Commander\nDamage Taken';
326+
327+
@override
328+
String get timesKilledByCommanderTitle => 'Killed by\nCommander Dmg';
329+
330+
@override
331+
String get bestColorComboTitle => 'Best Color\nCombo';
332+
333+
@override
334+
String get bestSingleColorTitle => 'Best Single\nColor';
335+
306336
@override
307337
String get underConstructionText => 'Under Construction';
308338

0 commit comments

Comments
 (0)