feat: analytics abstraction with debug backend and game event wiring

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 13:35:31 +09:00
parent 6d2d97bfcc
commit 074a21ea2b
7 changed files with 161 additions and 5 deletions
+33 -2
View File
@@ -160,6 +160,17 @@ class _GameScreenState extends ConsumerState<GameScreen>
ref
.read(seasonFlowProvider.notifier)
.recordWin(stars: next.starsEarned, score: next.score);
final flow = ref.read(seasonFlowProvider);
if (flow != null) {
ref.read(analyticsProvider).stageEnd(
seasonId: flow.pack.seasonId,
stageId: flow.stage.id,
won: true,
stars: next.starsEarned,
score: next.score,
movesUsed: next.moveLimit - next.movesLeft,
);
}
}
final stackBox =
_stackKey.currentContext?.findRenderObject() as RenderBox?;
@@ -171,8 +182,22 @@ class _GameScreenState extends ConsumerState<GameScreen>
if (next.phase == GamePhase.lost && next.endless) {
ref.read(endlessBestProvider.notifier).record(next.score).then((isNew) {
if (mounted) setState(() => _endlessNewBest = isNew);
ref.read(analyticsProvider).endlessEnd(score: next.score, isNewBest: isNew);
});
}
if (next.phase == GamePhase.lost && !next.endless) {
final flow = ref.read(seasonFlowProvider);
if (flow != null) {
ref.read(analyticsProvider).stageEnd(
seasonId: flow.pack.seasonId,
stageId: flow.stage.id,
won: false,
stars: 0,
score: next.score,
movesUsed: next.moveLimit - next.movesLeft,
);
}
}
if (next.phase == GamePhase.won || next.phase == GamePhase.lost) {
ref.read(streakProvider.notifier).onStagePlayed(DateTime.now());
}
@@ -367,7 +392,10 @@ class _GameScreenState extends ConsumerState<GameScreen>
l10n.outOfMoves,
[
FilledButton(
onPressed: notifier.addExtraMoves,
onPressed: () {
ref.read(analyticsProvider).rescueUsed(type: 'extra_moves');
notifier.addExtraMoves();
},
child: Text(l10n.plusFiveMoves),
),
TextButton(
@@ -380,7 +408,10 @@ class _GameScreenState extends ConsumerState<GameScreen>
l10n.boardFull,
[
FilledButton(
onPressed: notifier.useContinue,
onPressed: () {
ref.read(analyticsProvider).rescueUsed(type: 'continue');
notifier.useContinue();
},
child: Text(l10n.watchAdContinue),
),
TextButton(
+1
View File
@@ -90,6 +90,7 @@ class HomeScreen extends ConsumerWidget {
onPressed: () {
if (!(ModalRoute.of(context)?.isCurrent ?? true)) return;
ref.read(seasonFlowProvider.notifier).clear();
ref.read(analyticsProvider).endlessStart();
ref.read(gameSessionProvider.notifier).startStage(
StageConfig.endless(
seed: DateTime.now().millisecondsSinceEpoch,