Initial commit with gitignore
This commit is contained in:
279
lib/screens/home_screen.dart
Normal file
279
lib/screens/home_screen.dart
Normal file
@@ -0,0 +1,279 @@
|
||||
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user