import 'dart:math'; import 'package:flutter/material.dart'; import 'package:service_api/service_api.dart'; import 'package:service_api/models/assessment_data.dart'; class AssessmentScreen extends StatefulWidget { const AssessmentScreen({super.key}); @override State createState() => _AssessmentScreenState(); } class _AssessmentScreenState extends State { final Map _answers = {}; final PageController _pageController = PageController(); int _currentPage = 0; late final Map> _dailyQuestions; late final List _areaKeys; @override void initState() { super.initState(); _dailyQuestions = _generateDailyQuestions(); _areaKeys = _dailyQuestions.keys.toList(); } /// [핵심 로직] 전체 문제 풀에서 영역별로 8개씩 랜덤 추출 (총 32문항) Map> _generateDailyQuestions() { final random = Random(); Map> grouped = {}; // 1. 전체 질문 분류 Map> pool = {}; for (var q in rawAssessmentQuestions) { if (!pool.containsKey(q.area)) pool[q.area] = []; pool[q.area]!.add(q); } // 2. 각 영역에서 랜덤하게 8문제씩 추출 (총 32문제) // (데이터가 부족할 경우를 대비해 take 사용) pool.forEach((area, questions) { var shuffled = List.from(questions)..shuffle(random); grouped[area] = shuffled.take(8).toList(); // 👈 8개로 설정 }); return grouped; } void _submitResult() async { // 1. 점수 계산 Map scores = {}; int totalYesCount = 0; _dailyQuestions.forEach((area, questions) { int areaScore = 0; for (var q in questions) { if (_answers[q.id] == true) { areaScore++; totalYesCount++; } } scores[area] = areaScore; }); // 2. 히스토리 저장 final identityService = IdentityService(); await identityService.saveAssessmentResult(scores); if (!mounted) return; // 3. 결과 알림 (기준: 32문항 중 12개 이상이면 주의) String message = "진단 결과가 기록되었습니다."; if (totalYesCount >= 12) { message += "\n\n주의가 필요한 항목이 다수 확인되었습니다.\n($totalYesCount/32개 해당)\n꾸준한 훈련을 권장합니다."; } else { message += "\n\n현재 양호한 상태입니다.\n이 상태를 유지하기 위해 매일 훈련하세요!"; } showDialog( context: context, barrierDismissible: false, builder: (ctx) => AlertDialog( title: const Text('진단 완료'), content: Text(message), actions: [ TextButton( onPressed: () { Navigator.pop(ctx); Navigator.pop(context, true); }, child: const Text('확인'), ), ], ), ); } String _getAreaTitle(CognitiveArea area) { switch (area) { case CognitiveArea.memory: return "1. 기억력 체크"; case CognitiveArea.perception: return "2. 시공간/지남력 체크"; case CognitiveArea.calculation: return "3. 계산력/판단력 체크"; case CognitiveArea.attention: return "4. 주의력/집행기능 체크"; case CognitiveArea.language: return "5. 언어/구성 능력"; } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('자가 진단 체크리스트'), centerTitle: true, bottom: PreferredSize( preferredSize: const Size.fromHeight(4.0), child: LinearProgressIndicator( value: (_currentPage + 1) / _areaKeys.length, backgroundColor: Colors.grey[200], valueColor: AlwaysStoppedAnimation(Theme.of(context).primaryColor), ), ), ), body: Column( children: [ Padding( padding: const EdgeInsets.all(16.0), child: Text( _getAreaTitle(_areaKeys[_currentPage]), style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold), ), ), Expanded( child: PageView.builder( controller: _pageController, physics: const NeverScrollableScrollPhysics(), itemCount: _areaKeys.length, onPageChanged: (idx) { setState(() { _currentPage = idx; }); }, itemBuilder: (context, index) { final area = _areaKeys[index]; final questions = _dailyQuestions[area]!; return ListView.separated( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), itemCount: questions.length, separatorBuilder: (c, i) => const Divider(height: 1), itemBuilder: (context, qIndex) { final q = questions[qIndex]; final bool isChecked = _answers[q.id] ?? false; return CheckboxListTile( title: Text( q.text, style: TextStyle( fontSize: 16, color: isChecked ? Colors.black : Colors.grey[800], fontWeight: isChecked ? FontWeight.w600 : FontWeight.normal, ), ), value: isChecked, activeColor: Colors.redAccent, onChanged: (val) { setState(() { _answers[q.id] = val!; }); }, ); }, ); }, ), ), Padding( padding: const EdgeInsets.all(16.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (_currentPage > 0) ElevatedButton.icon( onPressed: () => _pageController.previousPage( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut ), icon: const Icon(Icons.arrow_back), label: const Text('이전'), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), ) else const SizedBox(width: 90), Text( "${_currentPage + 1} / ${_areaKeys.length}", style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ), if (_currentPage < _areaKeys.length - 1) ElevatedButton.icon( onPressed: () => _pageController.nextPage( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut ), icon: const Icon(Icons.arrow_forward), label: const Text('다음'), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), ) else ElevatedButton.icon( style: ElevatedButton.styleFrom( backgroundColor: Colors.blueAccent, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), ), onPressed: _submitResult, icon: const Icon(Icons.check), label: const Text('결과 제출'), ), ], ), ), ], ), ); } }