import 'package:flutter/material.dart'; import '../services/formation_generator.dart'; import '../data/formation_positions.dart'; class ResultScreen extends StatefulWidget { final ConstraintMode mode; final bool rareStyleOn; final String? selectedLeague; final String? selectedCardType; final List> playerPool; // チームスタイル重み final Map teamStyleWeights; const ResultScreen({ super.key, required this.mode, required this.rareStyleOn, required this.selectedLeague, required this.selectedCardType, required this.playerPool, required this.teamStyleWeights, }); @override State createState() => _ResultScreenState(); } class _ResultScreenState extends State { Map? _result; List> _visiblePlayers = []; bool _isAnimating = false; @override void initState() { super.initState(); _reroll(); } Future _reroll() async { setState(() { _result = null; _visiblePlayers = []; _isAnimating = true; }); final res = FormationGenerator.generate( mode: widget.mode, rareStyleOn: widget.rareStyleOn, selectedLeague: widget.selectedLeague, selectedCardType: widget.selectedCardType, playerPool: widget.playerPool, teamStyleWeights: widget.teamStyleWeights, ); setState(() => _result = res); final players = (res['positions'] as List).cast(); for (int i = 0; i < players.length; i++) { await Future.delayed(const Duration(milliseconds: 140)); setState(() { _visiblePlayers.add(Map.from(players[i])); }); } setState(() => _isAnimating = false); } // ========================= // タップでフルネーム表示 // ========================= void _showPlayerNameDialog(String fullName) { showDialog( context: context, builder: (_) => AlertDialog( title: const Text('選手名'), content: Text( fullName, style: const TextStyle(fontSize: 18), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('閉じる'), ), ], ), ); } // ピッチ上は名字だけ(本家っぽい) String _displayName(String fullName) { final name = fullName.trim(); if (name.isEmpty) return ''; if (!name.contains(' ')) return name; return name.split(RegExp(r'\s+')).last; } // ========================= // 色分け // ========================= Color _getColor(String pos) { if (pos == 'GK') return Colors.orange; if (['CB', 'LSB', 'RSB'].contains(pos)) return Colors.blue; if (['DMF', 'CMF', 'OMF', 'LMF', 'RMF'].contains(pos)) return Colors.green; if (['CF', 'ST', 'RWG', 'LWG'].contains(pos)) return Colors.red; return Colors.grey; } // ========================= // カード(タップ対応) // ========================= Widget _buildPlayerCard(Map data) { final pos = data['pos'] ?? ''; final style = data['style'] ?? ''; final fullName = data['name'] ?? ''; final color = _getColor(pos); // poolモードは name が主役、それ以外は style が主役 final middleText = (widget.mode == ConstraintMode.pool) ? (fullName.isEmpty ? '未登録' : _displayName(fullName)) : (_displayName(fullName)); final bottomText = (widget.mode == ConstraintMode.pool) ? '' : style; return GestureDetector( onTap: fullName.trim().isEmpty ? null : () => _showPlayerNameDialog(fullName), child: Container( width: 92, height: 74, decoration: BoxDecoration( color: color.withOpacity(0.9), borderRadius: BorderRadius.circular(10), border: Border.all(color: Colors.white, width: 1), ), padding: const EdgeInsets.all(6), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( pos, style: const TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 2), Text( middleText, textAlign: TextAlign.center, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( color: (widget.mode == ConstraintMode.pool && fullName.isEmpty) ? Colors.white70 : Colors.white, fontSize: 12, fontWeight: FontWeight.w800, ), ), const SizedBox(height: 2), Text( bottomText, textAlign: TextAlign.center, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: Colors.white, fontSize: 10, ), ), ], ), ), ); } // ========================= // ピッチ配置 // ========================= Widget _buildPitch(String formation, List> roles) { final layout = getFormationLayout(formation); return LayoutBuilder( builder: (context, constraints) { final width = constraints.maxWidth; final height = constraints.maxHeight; const cardW = 92.0; const cardH = 74.0; final children = [ Container( width: width, height: height, decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.green.shade800, Colors.green.shade700], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.white54, width: 2), ), ), ]; int index = 0; for (int row = 0; row < layout.length; row++) { for (int col = 0; col < layout[row].length; col++) { if (index >= roles.length) break; final data = roles[index++]; final xNorm = layout[row][col]['x'] ?? 0.5; final yNorm = layout[row][col]['y'] ?? 0.5; children.add( Positioned( left: width * xNorm - cardW / 2, top: height * yNorm - cardH / 2, child: _buildPlayerCard(data), ), ); } } return Stack(children: children); }, ); } @override Widget build(BuildContext context) { final formation = _result?['formation'] as String?; final label = _result?['constraintLabel'] as String?; final teamStyle = _result?['teamStyle'] as String?; return Scaffold( backgroundColor: Colors.green[900], appBar: AppBar( title: const Text('結果'), backgroundColor: Colors.green[900], ), body: Column( children: [ const SizedBox(height: 10), if (formation != null) Column( children: [ Text( 'フォーメーション: $formation', style: const TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), ), if (label != null) Text(label, style: const TextStyle(color: Colors.white70)), if (teamStyle != null) Text('チームスタイル: $teamStyle', style: const TextStyle(color: Colors.white70)), const SizedBox(height: 4), const Text( '※カードをタップでフルネーム表示', style: TextStyle(color: Colors.white54, fontSize: 12), ), ], ), const SizedBox(height: 10), Expanded( child: Padding( padding: const EdgeInsets.all(8), child: formation == null ? const Center( child: Text( '抽選中…', style: TextStyle(color: Colors.white70, fontSize: 16), ), ) : _buildPitch(formation, _visiblePlayers), ), ), Padding( padding: const EdgeInsets.fromLTRB(12, 0, 12, 16), child: SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: _isAnimating ? null : _reroll, icon: const Icon(Icons.shuffle), label: const Text('再抽選'), style: ElevatedButton.styleFrom( backgroundColor: Colors.white, foregroundColor: Colors.green[900], padding: const EdgeInsets.symmetric(vertical: 14), ), ), ), ), ], ), ); } }