074a21ea2b
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
65 lines
1.7 KiB
Dart
65 lines
1.7 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
|
|
/// Where events land. Phase 4 ships the debug logger; the Firebase backend
|
|
/// plugs in here after the owner runs flutterfire configure.
|
|
abstract class AnalyticsBackend {
|
|
void logEvent(String name, Map<String, Object> params);
|
|
}
|
|
|
|
class DebugAnalyticsBackend implements AnalyticsBackend {
|
|
@override
|
|
void logEvent(String name, Map<String, Object> params) {
|
|
debugPrint('[analytics] $name $params');
|
|
}
|
|
}
|
|
|
|
/// Typed event surface. Booleans are sent as 0/1 ints so every backend
|
|
/// (GA4 included) aggregates them the same way.
|
|
class AnalyticsService {
|
|
AnalyticsService(this._backend);
|
|
|
|
final AnalyticsBackend _backend;
|
|
|
|
void stageStart({required String seasonId, required String stageId}) {
|
|
_backend.logEvent('stage_start', {
|
|
'season_id': seasonId,
|
|
'stage_id': stageId,
|
|
});
|
|
}
|
|
|
|
void stageEnd({
|
|
required String seasonId,
|
|
required String stageId,
|
|
required bool won,
|
|
required int stars,
|
|
required int score,
|
|
required int movesUsed,
|
|
}) {
|
|
_backend.logEvent('stage_end', {
|
|
'season_id': seasonId,
|
|
'stage_id': stageId,
|
|
'won': won ? 1 : 0,
|
|
'stars': stars,
|
|
'score': score,
|
|
'moves_used': movesUsed,
|
|
});
|
|
}
|
|
|
|
void endlessStart() => _backend.logEvent('endless_start', const {});
|
|
|
|
void endlessEnd({required int score, required bool isNewBest}) {
|
|
_backend.logEvent('endless_end', {
|
|
'score': score,
|
|
'new_best': isNewBest ? 1 : 0,
|
|
});
|
|
}
|
|
|
|
void rescueUsed({required String type}) {
|
|
_backend.logEvent('rescue_used', {'type': type});
|
|
}
|
|
|
|
void tutorialFinished({required bool skipped}) {
|
|
_backend.logEvent('tutorial_finished', {'skipped': skipped ? 1 : 0});
|
|
}
|
|
}
|