import 'package:flutter/material.dart'; import 'package:asciineverdie/l10n/app_localizations.dart'; import 'package:asciineverdie/src/core/model/game_statistics.dart'; import 'package:asciineverdie/src/shared/widgets/retro_dialog.dart'; /// 게임 통계 다이얼로그 (Statistics Dialog) /// /// 세션 통계와 누적 통계를 탭으로 표시 class StatisticsDialog extends StatefulWidget { const StatisticsDialog({ super.key, required this.session, required this.cumulative, }); final SessionStatistics session; final CumulativeStatistics cumulative; /// 다이얼로그 표시 static Future show( BuildContext context, { required SessionStatistics session, required CumulativeStatistics cumulative, }) { return showDialog( context: context, barrierColor: Colors.black87, builder: (_) => StatisticsDialog(session: session, cumulative: cumulative), ); } @override State createState() => _StatisticsDialogState(); } class _StatisticsDialogState extends State with SingleTickerProviderStateMixin { late TabController _tabController; @override void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this); } @override void dispose() { _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final l10n = L10n.of(context); return RetroDialog( title: l10n.statsStatistics, titleIcon: '📊', maxWidth: 420, maxHeight: 520, child: Column( children: [ // 탭 바 RetroTabBar( controller: _tabController, tabs: [l10n.statsSession, l10n.statsAccumulated], ), // 탭 내용 Expanded( child: TabBarView( controller: _tabController, children: [ _SessionStatisticsView(stats: widget.session), _CumulativeStatisticsView(stats: widget.cumulative), ], ), ), ], ), ); } } /// 세션 통계 뷰 class _SessionStatisticsView extends StatelessWidget { const _SessionStatisticsView({required this.stats}); final SessionStatistics stats; @override Widget build(BuildContext context) { final l10n = L10n.of(context); return ListView( padding: const EdgeInsets.all(12), children: [ _StatSection( title: l10n.statsCombat, icon: '⚔', items: [ _StatItem( label: l10n.statsPlayTime, value: stats.formattedPlayTime, ), _StatItem( label: l10n.statsMonstersKilled, value: _formatNumber(stats.monstersKilled), ), _StatItem( label: l10n.statsBossesDefeated, value: _formatNumber(stats.bossesDefeated), ), _StatItem( label: l10n.statsDeaths, value: _formatNumber(stats.deathCount), ), ], ), const SizedBox(height: 12), _StatSection( title: l10n.statsDamage, icon: '⚡', items: [ _StatItem( label: l10n.statsDamageDealt, value: _formatNumber(stats.totalDamageDealt), ), _StatItem( label: l10n.statsDamageTaken, value: _formatNumber(stats.totalDamageTaken), ), _StatItem( label: l10n.statsAverageDps, value: stats.averageDps.toStringAsFixed(1), ), ], ), const SizedBox(height: 12), _StatSection( title: l10n.statsSkills, icon: '✧', items: [ _StatItem( label: l10n.statsSkillsUsed, value: _formatNumber(stats.skillsUsed), ), _StatItem( label: l10n.statsCriticalHits, value: _formatNumber(stats.criticalHits), ), _StatItem( label: l10n.statsMaxCriticalStreak, value: _formatNumber(stats.maxCriticalStreak), ), _StatItem( label: l10n.statsCriticalRate, value: '${(stats.criticalRate * 100).toStringAsFixed(1)}%', ), ], ), const SizedBox(height: 12), _StatSection( title: l10n.statsEconomy, icon: '💰', items: [ _StatItem( label: l10n.statsGoldEarned, value: _formatNumber(stats.goldEarned), ), _StatItem( label: l10n.statsGoldSpent, value: _formatNumber(stats.goldSpent), ), _StatItem( label: l10n.statsItemsSold, value: _formatNumber(stats.itemsSold), ), _StatItem( label: l10n.statsPotionsUsed, value: _formatNumber(stats.potionsUsed), ), ], ), const SizedBox(height: 12), _StatSection( title: l10n.statsProgress, icon: '↑', items: [ _StatItem( label: l10n.statsLevelUps, value: _formatNumber(stats.levelUps), ), _StatItem( label: l10n.statsQuestsCompleted, value: _formatNumber(stats.questsCompleted), ), ], ), ], ); } } /// 누적 통계 뷰 class _CumulativeStatisticsView extends StatelessWidget { const _CumulativeStatisticsView({required this.stats}); final CumulativeStatistics stats; @override Widget build(BuildContext context) { final l10n = L10n.of(context); return ListView( padding: const EdgeInsets.all(12), children: [ _StatSection( title: l10n.statsRecords, icon: '🏆', items: [ _StatItem( label: l10n.statsHighestLevel, value: _formatNumber(stats.highestLevel), highlight: true, ), _StatItem( label: l10n.statsHighestGoldHeld, value: _formatNumber(stats.highestGoldHeld), highlight: true, ), _StatItem( label: l10n.statsBestCriticalStreak, value: _formatNumber(stats.bestCriticalStreak), highlight: true, ), ], ), const SizedBox(height: 12), _StatSection( title: l10n.statsTotalPlay, icon: '⏱', items: [ _StatItem( label: l10n.statsTotalPlayTime, value: stats.formattedTotalPlayTime, ), _StatItem( label: l10n.statsGamesStarted, value: _formatNumber(stats.gamesStarted), ), _StatItem( label: l10n.statsGamesCompleted, value: _formatNumber(stats.gamesCompleted), ), _StatItem( label: l10n.statsCompletionRate, value: '${(stats.completionRate * 100).toStringAsFixed(1)}%', ), ], ), const SizedBox(height: 12), _StatSection( title: l10n.statsTotalCombat, icon: '⚔', items: [ _StatItem( label: l10n.statsMonstersKilled, value: _formatNumber(stats.totalMonstersKilled), ), _StatItem( label: l10n.statsBossesDefeated, value: _formatNumber(stats.totalBossesDefeated), ), _StatItem( label: l10n.statsTotalDeaths, value: _formatNumber(stats.totalDeaths), ), _StatItem( label: l10n.statsTotalLevelUps, value: _formatNumber(stats.totalLevelUps), ), ], ), const SizedBox(height: 12), _StatSection( title: l10n.statsTotalDamage, icon: '⚡', items: [ _StatItem( label: l10n.statsDamageDealt, value: _formatNumber(stats.totalDamageDealt), ), _StatItem( label: l10n.statsDamageTaken, value: _formatNumber(stats.totalDamageTaken), ), ], ), const SizedBox(height: 12), _StatSection( title: l10n.statsTotalSkills, icon: '✧', items: [ _StatItem( label: l10n.statsSkillsUsed, value: _formatNumber(stats.totalSkillsUsed), ), _StatItem( label: l10n.statsCriticalHits, value: _formatNumber(stats.totalCriticalHits), ), ], ), const SizedBox(height: 12), _StatSection( title: l10n.statsTotalEconomy, icon: '💰', items: [ _StatItem( label: l10n.statsGoldEarned, value: _formatNumber(stats.totalGoldEarned), ), _StatItem( label: l10n.statsGoldSpent, value: _formatNumber(stats.totalGoldSpent), ), _StatItem( label: l10n.statsItemsSold, value: _formatNumber(stats.totalItemsSold), ), _StatItem( label: l10n.statsPotionsUsed, value: _formatNumber(stats.totalPotionsUsed), ), _StatItem( label: l10n.statsQuestsCompleted, value: _formatNumber(stats.totalQuestsCompleted), ), ], ), ], ); } } /// 레트로 스타일 통계 섹션 위젯 class _StatSection extends StatelessWidget { const _StatSection({ required this.title, required this.icon, required this.items, }); final String title; final String icon; final List<_StatItem> items; @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 섹션 헤더 (테마에서 자동 결정) RetroSectionHeader(title: title, icon: icon), // 통계 항목들 ...items, ], ); } } /// 레트로 스타일 개별 통계 항목 위젯 class _StatItem extends StatelessWidget { const _StatItem({ required this.label, required this.value, this.highlight = false, }); final String label; final String value; final bool highlight; @override Widget build(BuildContext context) { return RetroStatRow(label: label, value: value, highlight: highlight); } } /// 숫자 포맷팅 (천 단위 콤마) String _formatNumber(int value) { if (value < 1000) return value.toString(); final result = StringBuffer(); final str = value.toString(); final length = str.length; for (var i = 0; i < length; i++) { if (i > 0 && (length - i) % 3 == 0) { result.write(','); } result.write(str[i]); } return result.toString(); }