feat(statistics): 게임 통계 시스템 추가

- GameStatistics 모델 (전투, 퀘스트, 아이템 통계)
- StatisticsStorage 영구 저장
- StatisticsDialog UI
This commit is contained in:
JiWoong Sul
2025-12-30 15:58:22 +09:00
parent 80b6cd63e3
commit d64b9654a3
3 changed files with 1457 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
import 'dart:convert';
import 'dart:io';
import 'package:askiineverdie/src/core/model/game_statistics.dart';
import 'package:path_provider/path_provider.dart';
/// 게임 통계 저장소 (Statistics Storage)
///
/// 누적 통계 데이터 저장/로드 관리
class StatisticsStorage {
StatisticsStorage();
static const String _fileName = 'game_statistics.json';
Directory? _storageDir;
Future<Directory> _getStorageDir() async {
if (_storageDir != null) return _storageDir!;
_storageDir = await getApplicationSupportDirectory();
return _storageDir!;
}
File _getFile(Directory dir) {
return File('${dir.path}/$_fileName');
}
/// 누적 통계 로드
Future<CumulativeStatistics> loadCumulative() async {
try {
final dir = await _getStorageDir();
final file = _getFile(dir);
if (!await file.exists()) {
return CumulativeStatistics.empty();
}
final content = await file.readAsString();
final json = jsonDecode(content) as Map<String, dynamic>;
// cumulative 키가 있으면 해당 데이터 사용
if (json.containsKey('cumulative')) {
return CumulativeStatistics.fromJson(
json['cumulative'] as Map<String, dynamic>,
);
}
// 직접 CumulativeStatistics JSON인 경우
return CumulativeStatistics.fromJson(json);
} catch (e) {
// 파일이 없거나 손상된 경우 빈 통계 반환
return CumulativeStatistics.empty();
}
}
/// 누적 통계 저장
Future<bool> saveCumulative(CumulativeStatistics stats) async {
try {
final dir = await _getStorageDir();
final file = _getFile(dir);
final json = {
'version': 1,
'lastUpdated': DateTime.now().toIso8601String(),
'cumulative': stats.toJson(),
};
final content = const JsonEncoder.withIndent(' ').convert(json);
await file.writeAsString(content);
return true;
} catch (e) {
return false;
}
}
/// 세션 종료 시 누적 통계 업데이트
Future<bool> mergeSession(SessionStatistics session) async {
final current = await loadCumulative();
final updated = current.mergeSession(session);
return saveCumulative(updated);
}
/// 최고 레벨 업데이트
Future<bool> updateHighestLevel(int level) async {
final current = await loadCumulative();
if (level <= current.highestLevel) return true;
final updated = current.updateHighestLevel(level);
return saveCumulative(updated);
}
/// 최대 골드 업데이트
Future<bool> updateHighestGold(int gold) async {
final current = await loadCumulative();
if (gold <= current.highestGoldHeld) return true;
final updated = current.updateHighestGold(gold);
return saveCumulative(updated);
}
/// 새 게임 시작 기록
Future<bool> recordGameStart() async {
final current = await loadCumulative();
final updated = current.recordGameStart();
return saveCumulative(updated);
}
/// 게임 클리어 기록
Future<bool> recordGameComplete() async {
final current = await loadCumulative();
final updated = current.recordGameComplete();
return saveCumulative(updated);
}
/// 통계 초기화 (테스트용)
Future<bool> clear() async {
try {
final dir = await _getStorageDir();
final file = _getFile(dir);
if (await file.exists()) {
await file.delete();
}
return true;
} catch (e) {
return false;
}
}
}