feat(hall): Phase 10 명예의 전당 시스템 구현

- HallOfFameEntry 모델 및 HallOfFame 컬렉션 추가
- HallOfFameStorage 저장소 (JSON 파일 기반)
- HallOfFameScreen UI (순위별 색상/아이콘)
- 게임 클리어 시 명예의 전당 등록 처리
- FrontScreen에 명예의 전당 버튼 추가
- 클리어 축하 다이얼로그 구현
This commit is contained in:
JiWoong Sul
2025-12-17 18:57:26 +09:00
parent 7c7f3b0d9e
commit 9af5c4dc13
6 changed files with 814 additions and 2 deletions

View File

@@ -0,0 +1,81 @@
import 'dart:convert';
import 'dart:io';
import 'package:askiineverdie/src/core/model/hall_of_fame.dart';
import 'package:path_provider/path_provider.dart';
/// 명예의 전당 저장소 (Phase 10: Hall of Fame Storage)
///
/// 명예의 전당 데이터 저장/로드 관리
class HallOfFameStorage {
HallOfFameStorage();
static const String _fileName = 'hall_of_fame.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<HallOfFame> load() async {
try {
final dir = await _getStorageDir();
final file = _getFile(dir);
if (!await file.exists()) {
return HallOfFame.empty();
}
final content = await file.readAsString();
final json = jsonDecode(content) as Map<String, dynamic>;
return HallOfFame.fromJson(json);
} catch (e) {
// 파일이 없거나 손상된 경우 빈 명예의 전당 반환
return HallOfFame.empty();
}
}
/// 명예의 전당 저장
Future<bool> save(HallOfFame hallOfFame) async {
try {
final dir = await _getStorageDir();
final file = _getFile(dir);
final content = jsonEncode(hallOfFame.toJson());
await file.writeAsString(content);
return true;
} catch (e) {
return false;
}
}
/// 새 엔트리 추가 및 저장
Future<bool> addEntry(HallOfFameEntry entry) async {
final hallOfFame = await load();
final updated = hallOfFame.addEntry(entry);
return save(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;
}
}
}