import 'package:flutter/material.dart'; import 'package:askiineverdie/src/core/model/game_statistics.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, 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 theme = Theme.of(context); final isKorean = Localizations.localeOf(context).languageCode == 'ko'; final isJapanese = Localizations.localeOf(context).languageCode == 'ja'; return Dialog( child: Container( constraints: const BoxConstraints(maxWidth: 400, maxHeight: 500), child: Column( mainAxisSize: MainAxisSize.min, children: [ // 헤더 Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: theme.colorScheme.primaryContainer, borderRadius: const BorderRadius.vertical( top: Radius.circular(28), ), ), child: Row( children: [ Icon( Icons.bar_chart, color: theme.colorScheme.onPrimaryContainer, ), const SizedBox(width: 12), Expanded( child: Text( isKorean ? '게임 통계' : isJapanese ? 'ゲーム統計' : 'Game Statistics', style: theme.textTheme.titleLarge?.copyWith( color: theme.colorScheme.onPrimaryContainer, ), ), ), IconButton( icon: const Icon(Icons.close), onPressed: () => Navigator.of(context).pop(), color: theme.colorScheme.onPrimaryContainer, ), ], ), ), // 탭 바 TabBar( controller: _tabController, tabs: [ Tab( text: isKorean ? '현재 세션' : isJapanese ? '現在のセッション' : 'Session', ), Tab( text: isKorean ? '누적 통계' : isJapanese ? '累積統計' : 'Cumulative', ), ], ), // 탭 내용 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 isKorean = Localizations.localeOf(context).languageCode == 'ko'; final isJapanese = Localizations.localeOf(context).languageCode == 'ja'; return ListView( padding: const EdgeInsets.all(16), children: [ _StatSection( title: isKorean ? '전투' : isJapanese ? '戦闘' : 'Combat', icon: Icons.sports_mma, items: [ _StatItem( label: isKorean ? '플레이 시간' : isJapanese ? 'プレイ時間' : 'Play Time', value: stats.formattedPlayTime, ), _StatItem( label: isKorean ? '처치한 몬스터' : isJapanese ? '倒したモンスター' : 'Monsters Killed', value: _formatNumber(stats.monstersKilled), ), _StatItem( label: isKorean ? '보스 처치' : isJapanese ? 'ボス討伐' : 'Bosses Defeated', value: _formatNumber(stats.bossesDefeated), ), _StatItem( label: isKorean ? '사망 횟수' : isJapanese ? '死亡回数' : 'Deaths', value: _formatNumber(stats.deathCount), ), ], ), const SizedBox(height: 16), _StatSection( title: isKorean ? '데미지' : isJapanese ? 'ダメージ' : 'Damage', icon: Icons.flash_on, items: [ _StatItem( label: isKorean ? '입힌 데미지' : isJapanese ? '与えたダメージ' : 'Damage Dealt', value: _formatNumber(stats.totalDamageDealt), ), _StatItem( label: isKorean ? '받은 데미지' : isJapanese ? '受けたダメージ' : 'Damage Taken', value: _formatNumber(stats.totalDamageTaken), ), _StatItem( label: isKorean ? '평균 DPS' : isJapanese ? '平均DPS' : 'Average DPS', value: stats.averageDps.toStringAsFixed(1), ), ], ), const SizedBox(height: 16), _StatSection( title: isKorean ? '스킬' : isJapanese ? 'スキル' : 'Skills', icon: Icons.auto_awesome, items: [ _StatItem( label: isKorean ? '스킬 사용' : isJapanese ? 'スキル使用' : 'Skills Used', value: _formatNumber(stats.skillsUsed), ), _StatItem( label: isKorean ? '크리티컬 히트' : isJapanese ? 'クリティカルヒット' : 'Critical Hits', value: _formatNumber(stats.criticalHits), ), _StatItem( label: isKorean ? '최대 연속 크리티컬' : isJapanese ? '最大連続クリティカル' : 'Max Critical Streak', value: _formatNumber(stats.maxCriticalStreak), ), _StatItem( label: isKorean ? '크리티컬 비율' : isJapanese ? 'クリティカル率' : 'Critical Rate', value: '${(stats.criticalRate * 100).toStringAsFixed(1)}%', ), ], ), const SizedBox(height: 16), _StatSection( title: isKorean ? '경제' : isJapanese ? '経済' : 'Economy', icon: Icons.monetization_on, items: [ _StatItem( label: isKorean ? '획득 골드' : isJapanese ? '獲得ゴールド' : 'Gold Earned', value: _formatNumber(stats.goldEarned), ), _StatItem( label: isKorean ? '소비 골드' : isJapanese ? '消費ゴールド' : 'Gold Spent', value: _formatNumber(stats.goldSpent), ), _StatItem( label: isKorean ? '판매 아이템' : isJapanese ? '売却アイテム' : 'Items Sold', value: _formatNumber(stats.itemsSold), ), _StatItem( label: isKorean ? '물약 사용' : isJapanese ? 'ポーション使用' : 'Potions Used', value: _formatNumber(stats.potionsUsed), ), ], ), const SizedBox(height: 16), _StatSection( title: isKorean ? '진행' : isJapanese ? '進行' : 'Progress', icon: Icons.trending_up, items: [ _StatItem( label: isKorean ? '레벨업' : isJapanese ? 'レベルアップ' : 'Level Ups', value: _formatNumber(stats.levelUps), ), _StatItem( label: isKorean ? '완료한 퀘스트' : isJapanese ? '完了したクエスト' : 'Quests Completed', value: _formatNumber(stats.questsCompleted), ), ], ), ], ); } } /// 누적 통계 뷰 class _CumulativeStatisticsView extends StatelessWidget { const _CumulativeStatisticsView({required this.stats}); final CumulativeStatistics stats; @override Widget build(BuildContext context) { final isKorean = Localizations.localeOf(context).languageCode == 'ko'; final isJapanese = Localizations.localeOf(context).languageCode == 'ja'; return ListView( padding: const EdgeInsets.all(16), children: [ _StatSection( title: isKorean ? '기록' : isJapanese ? '記録' : 'Records', icon: Icons.emoji_events, items: [ _StatItem( label: isKorean ? '최고 레벨' : isJapanese ? '最高レベル' : 'Highest Level', value: _formatNumber(stats.highestLevel), highlight: true, ), _StatItem( label: isKorean ? '최대 보유 골드' : isJapanese ? '最大所持ゴールド' : 'Highest Gold Held', value: _formatNumber(stats.highestGoldHeld), highlight: true, ), _StatItem( label: isKorean ? '최고 연속 크리티컬' : isJapanese ? '最高連続クリティカル' : 'Best Critical Streak', value: _formatNumber(stats.bestCriticalStreak), highlight: true, ), ], ), const SizedBox(height: 16), _StatSection( title: isKorean ? '총 플레이' : isJapanese ? '総プレイ' : 'Total Play', icon: Icons.access_time, items: [ _StatItem( label: isKorean ? '총 플레이 시간' : isJapanese ? '総プレイ時間' : 'Total Play Time', value: stats.formattedTotalPlayTime, ), _StatItem( label: isKorean ? '시작한 게임' : isJapanese ? '開始したゲーム' : 'Games Started', value: _formatNumber(stats.gamesStarted), ), _StatItem( label: isKorean ? '클리어한 게임' : isJapanese ? 'クリアしたゲーム' : 'Games Completed', value: _formatNumber(stats.gamesCompleted), ), _StatItem( label: isKorean ? '클리어율' : isJapanese ? 'クリア率' : 'Completion Rate', value: '${(stats.completionRate * 100).toStringAsFixed(1)}%', ), ], ), const SizedBox(height: 16), _StatSection( title: isKorean ? '총 전투' : isJapanese ? '総戦闘' : 'Total Combat', icon: Icons.sports_mma, items: [ _StatItem( label: isKorean ? '처치한 몬스터' : isJapanese ? '倒したモンスター' : 'Monsters Killed', value: _formatNumber(stats.totalMonstersKilled), ), _StatItem( label: isKorean ? '보스 처치' : isJapanese ? 'ボス討伐' : 'Bosses Defeated', value: _formatNumber(stats.totalBossesDefeated), ), _StatItem( label: isKorean ? '총 사망' : isJapanese ? '総死亡' : 'Total Deaths', value: _formatNumber(stats.totalDeaths), ), _StatItem( label: isKorean ? '총 레벨업' : isJapanese ? '総レベルアップ' : 'Total Level Ups', value: _formatNumber(stats.totalLevelUps), ), ], ), const SizedBox(height: 16), _StatSection( title: isKorean ? '총 데미지' : isJapanese ? '総ダメージ' : 'Total Damage', icon: Icons.flash_on, items: [ _StatItem( label: isKorean ? '입힌 데미지' : isJapanese ? '与えたダメージ' : 'Damage Dealt', value: _formatNumber(stats.totalDamageDealt), ), _StatItem( label: isKorean ? '받은 데미지' : isJapanese ? '受けたダメージ' : 'Damage Taken', value: _formatNumber(stats.totalDamageTaken), ), ], ), const SizedBox(height: 16), _StatSection( title: isKorean ? '총 스킬' : isJapanese ? '総スキル' : 'Total Skills', icon: Icons.auto_awesome, items: [ _StatItem( label: isKorean ? '스킬 사용' : isJapanese ? 'スキル使用' : 'Skills Used', value: _formatNumber(stats.totalSkillsUsed), ), _StatItem( label: isKorean ? '크리티컬 히트' : isJapanese ? 'クリティカルヒット' : 'Critical Hits', value: _formatNumber(stats.totalCriticalHits), ), ], ), const SizedBox(height: 16), _StatSection( title: isKorean ? '총 경제' : isJapanese ? '総経済' : 'Total Economy', icon: Icons.monetization_on, items: [ _StatItem( label: isKorean ? '획득 골드' : isJapanese ? '獲得ゴールド' : 'Gold Earned', value: _formatNumber(stats.totalGoldEarned), ), _StatItem( label: isKorean ? '소비 골드' : isJapanese ? '消費ゴールド' : 'Gold Spent', value: _formatNumber(stats.totalGoldSpent), ), _StatItem( label: isKorean ? '판매 아이템' : isJapanese ? '売却アイテム' : 'Items Sold', value: _formatNumber(stats.totalItemsSold), ), _StatItem( label: isKorean ? '물약 사용' : isJapanese ? 'ポーション使用' : 'Potions Used', value: _formatNumber(stats.totalPotionsUsed), ), _StatItem( label: isKorean ? '완료 퀘스트' : isJapanese ? '完了クエスト' : 'Quests Completed', value: _formatNumber(stats.totalQuestsCompleted), ), ], ), ], ); } } /// 통계 섹션 위젯 class _StatSection extends StatelessWidget { const _StatSection({ required this.title, required this.icon, required this.items, }); final String title; final IconData icon; final List<_StatItem> items; @override Widget build(BuildContext context) { final theme = Theme.of(context); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 섹션 헤더 Row( children: [ Icon(icon, size: 18, color: theme.colorScheme.primary), const SizedBox(width: 8), Text( title, style: theme.textTheme.titleSmall?.copyWith( fontWeight: FontWeight.bold, color: theme.colorScheme.primary, ), ), ], ), const Divider(height: 8), // 통계 항목들 ...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) { final theme = Theme.of(context); return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( label, style: theme.textTheme.bodyMedium?.copyWith( color: theme.colorScheme.onSurfaceVariant, ), ), Container( padding: highlight ? const EdgeInsets.symmetric(horizontal: 8, vertical: 2) : null, decoration: highlight ? BoxDecoration( color: theme.colorScheme.primaryContainer, borderRadius: BorderRadius.circular(4), ) : null, child: Text( value, style: theme.textTheme.bodyMedium?.copyWith( fontWeight: FontWeight.bold, fontFamily: 'monospace', color: highlight ? theme.colorScheme.onPrimaryContainer : theme.colorScheme.onSurface, ), ), ), ], ), ); } } /// 숫자 포맷팅 (천 단위 콤마) 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(); }