games/packages/service_api/lib/services/brain_training_service.dart

83 lines
2.9 KiB
Dart
Raw Normal View History

2025-12-15 18:18:17 +09:00
import 'dart:math';
import '../models/cognitive_type.dart';
import '../models/assessment_data.dart';
class BrainTrainingService {
final Random _random = Random();
/// 사용자 취약점을 분석하여 맞춤형 게임 3개를 추천합니다.
List<BrainGameType> recommendGames(Map<CognitiveArea, int>? scores) {
if (scores == null || scores.isEmpty) {
// 기록이 없으면 골고루 추천 (기억, 계산, 주의)
return [
BrainGameType.sequence,
BrainGameType.mathQuiz,
BrainGameType.schulte,
];
}
// 1. 점수 기반 취약점 분석 (점수가 높을수록 위험/취약)
Map<CognitiveArea, double> riskRatios = {};
Map<CognitiveArea, int> totalCountByArea = {};
for (var q in rawAssessmentQuestions) {
totalCountByArea[q.area] = (totalCountByArea[q.area] ?? 0) + 1;
}
scores.forEach((area, score) {
int total = totalCountByArea[area] ?? 1;
riskRatios[area] = score / total;
});
var sortedRisks = riskRatios.entries.toList()
..sort((a, b) => b.value.compareTo(a.value));
CognitiveArea primaryWeakness = sortedRisks[0].key;
CognitiveArea secondaryWeakness = sortedRisks.length > 1 ? sortedRisks[1].key : primaryWeakness;
List<BrainGameType> recommendation = [];
// 2. 추천 리스트 생성
// (1) 가장 취약한 영역의 게임
recommendation.add(_getGameForArea(primaryWeakness));
// (2) 두 번째 취약한 영역의 게임 (중복 방지)
BrainGameType secondGame = _getGameForArea(secondaryWeakness);
if (!recommendation.contains(secondGame)) {
recommendation.add(secondGame);
} else {
recommendation.add(_getRandomGameExcluding(recommendation));
}
// (3) 랜덤 게임 (밸런스)
recommendation.add(_getRandomGameExcluding(recommendation));
return recommendation;
}
/// 영역별 게임 랜덤 선택 (2개 중 1개)
BrainGameType _getGameForArea(CognitiveArea area) {
switch (area) {
case CognitiveArea.memory:
return _random.nextBool() ? BrainGameType.sequence : BrainGameType.cardFlip;
case CognitiveArea.calculation:
return _random.nextBool() ? BrainGameType.mathQuiz : BrainGameType.sudoku;
case CognitiveArea.attention:
return _random.nextBool() ? BrainGameType.colorMatch : BrainGameType.schulte; // 슐테(숫자찾기)
case CognitiveArea.perception:
return _random.nextBool() ? BrainGameType.findDiff : BrainGameType.tracing; // 따라그리기
case CognitiveArea.language:
return _random.nextBool() ? BrainGameType.readAloud : BrainGameType.dictation; // 읽기/쓰기
}
}
BrainGameType _getRandomGameExcluding(List<BrainGameType> exclude) {
var candidates = BrainGameType.values.where((g) => !exclude.contains(g)).toList();
if (candidates.isEmpty) return BrainGameType.sudoku;
return candidates[_random.nextInt(candidates.length)];
}
}