Files
22e1372-efootballnexus/lib/screens/home_screen.dart

280 lines
8.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../services/formation_generator.dart';
import '../data/league_data.dart';
import '../data/cardtype_data.dart';
import 'result_screen.dart';
import '../models/player.dart';
import 'pool_screen.dart';
const allRoles = [
'GK',
'CB', 'LSB', 'RSB',
'DMF', 'CMF', 'OMF', 'LMF', 'RMF',
'CF', 'ST', 'RWG', 'LWG',
];
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
static const _poolKey = 'player_pool_v1';
ConstraintMode _mode = ConstraintMode.playstyle;
bool _rareStyleOn = false;
String? _selectedLeague;
String? _selectedCardType;
// 保存対象:選手プール
List<Map<String, dynamic>> _playerPool = [];
// ★チムスタ重み0〜100の重み。合計は気にしない
final Map<String, int> _teamStyleWeights = {
'ポゼッション': 50,
'ショートカウンター': 50,
'ロングカウンター': 50,
'サイドアタック': 50,
'ロングボール': 50,
};
@override
void initState() {
super.initState();
_loadPool();
}
Future<void> _loadPool() async {
final prefs = await SharedPreferences.getInstance();
final raw = prefs.getString(_poolKey);
if (raw == null || raw.isEmpty) return;
try {
final decoded = jsonDecode(raw) as List;
setState(() {
_playerPool = decoded
.map((e) => {
'name': (e['name'] ?? '').toString(),
'positions': List<String>.from(e['positions'] ?? const []),
})
.toList();
});
} catch (_) {
// 破損時は無視
}
}
Future<void> _savePool() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_poolKey, jsonEncode(_playerPool));
}
Future<void> _openPoolManager() async {
// Map -> Player
final currentPlayers = _playerPool.map((m) => Player.fromMap(m)).toList();
final updated = await Navigator.push<List<Player>>(
context,
MaterialPageRoute(
builder: (_) => PoolScreen(initial: currentPlayers),
),
);
if (updated != null) {
final mapped = updated.map((p) => p.toMap()).toList();
setState(() => _playerPool = mapped);
await _savePool();
}
}
// ★チムスタスライダー部品
Widget _teamStyleSlider(String label) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'$label : ${_teamStyleWeights[label]}',
style: const TextStyle(color: Colors.white),
),
Slider(
value: (_teamStyleWeights[label] ?? 0).toDouble(),
min: 0,
max: 100,
divisions: 100,
onChanged: (v) => setState(() {
_teamStyleWeights[label] = v.round();
}),
),
],
);
}
void _goResult() {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => ResultScreen(
mode: _mode,
rareStyleOn: _rareStyleOn,
selectedLeague: _selectedLeague,
selectedCardType: _selectedCardType,
playerPool: _playerPool,
teamStyleWeights: _teamStyleWeights, // ★追加Resultへ渡す
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.green[900],
appBar: AppBar(
title: const Text('efootball スカッドメーカー'),
backgroundColor: Colors.green[900],
actions: [
IconButton(
onPressed: _openPoolManager,
icon: const Icon(Icons.people_alt),
tooltip: '選手プール',
),
],
),
body: ListView(
padding: const EdgeInsets.all(12),
children: [
Row(
children: [
Expanded(
child: Text(
'登録選手: ${_playerPool.length}',
style: const TextStyle(color: Colors.white70),
),
),
TextButton(
onPressed: _openPoolManager,
child: const Text('選手プール'),
),
],
),
const SizedBox(height: 8),
DropdownButtonFormField<ConstraintMode>(
value: _mode,
decoration: const InputDecoration(
labelText: '遊び方(縛り)',
filled: true,
),
items: const [
DropdownMenuItem(
value: ConstraintMode.playstyle,
child: Text('プレースタイル縛り'),
),
DropdownMenuItem(
value: ConstraintMode.league,
child: Text('リーグ縛り'),
),
DropdownMenuItem(
value: ConstraintMode.cardType,
child: Text('カードタイプ縛り'),
),
DropdownMenuItem(
value: ConstraintMode.pool,
child: Text('選手プール抽選'),
),
],
onChanged: (v) {
if (v == null) return;
setState(() {
_mode = v;
if (_mode != ConstraintMode.league) _selectedLeague = null;
if (_mode != ConstraintMode.cardType) _selectedCardType = null;
});
},
),
const SizedBox(height: 10),
if (_mode == ConstraintMode.playstyle)
SwitchListTile(
title: const Text(
'希少なプレースタイルを出したい時にON',
style: TextStyle(color: Colors.white),
),
value: _rareStyleOn,
onChanged: (v) => setState(() => _rareStyleOn = v),
),
if (_mode == ConstraintMode.league)
DropdownButtonFormField<String?>(
value: _selectedLeague,
decoration: const InputDecoration(
labelText: 'リーグ(ランダム=ポジション別)',
filled: true,
),
items: [
const DropdownMenuItem<String?>(
value: null,
child: Text('ランダム'),
),
...leagues.map(
(l) => DropdownMenuItem<String?>(value: l, child: Text(l)),
),
],
onChanged: (v) => setState(() => _selectedLeague = v),
),
if (_mode == ConstraintMode.cardType)
DropdownButtonFormField<String?>(
value: _selectedCardType,
decoration: const InputDecoration(
labelText: 'カードタイプ(ランダム=ポジション別)',
filled: true,
),
items: [
const DropdownMenuItem<String?>(
value: null,
child: Text('ランダム'),
),
...cardTypes.map(
(c) => DropdownMenuItem<String?>(value: c, child: Text(c)),
),
],
onChanged: (v) => setState(() => _selectedCardType = v),
),
// ★チムスタ確率UI
const SizedBox(height: 12),
const Text(
'チームスタイル確率(重み)',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
_teamStyleSlider('ポゼッション'),
_teamStyleSlider('ショートカウンター'),
_teamStyleSlider('ロングカウンター'),
_teamStyleSlider('サイドアタック'),
_teamStyleSlider('ロングボール'),
const SizedBox(height: 14),
ElevatedButton.icon(
onPressed: _goResult,
icon: const Icon(Icons.arrow_forward),
label: const Text('結果を見る(抽選)'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
foregroundColor: Colors.green[900],
padding: const EdgeInsets.symmetric(vertical: 14),
),
),
],
),
);
}
}