ponshu-room-lite/lib/services/gamification_service.dart

142 lines
5.2 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hive_flutter/hive_flutter.dart';
import '../models/sake_item.dart';
import '../providers/theme_provider.dart';
/// Badge unlock result
class BadgeUnlock {
final String id;
final String name;
final String icon;
BadgeUnlock(this.id, this.name, this.icon);
}
/// Gamification Service: Badge unlock logic
class GamificationService {
/// Check badge conditions and unlock new badges
/// Returns: List of newly unlocked badges
static Future<List<BadgeUnlock>> checkAndUnlockBadges(WidgetRef ref) async {
final userProfile = ref.read(userProfileProvider);
final unlockedBadges = userProfile.unlockedBadges.toSet();
final newlyUnlocked = <BadgeUnlock>[];
// Get all SakeItems from Hive
final box = Hive.box<SakeItem>('sake_items');
final allItems = box.values.toList();
// 1. Badge: 初めての一歩 (first_step)
// Condition: Register at least 1 sake
if (!unlockedBadges.contains('first_step') && allItems.isNotEmpty) {
newlyUnlocked.add(BadgeUnlock('first_step', '初めての一歩', '🍶'));
}
// 2. Badge: 東北制覇 (regional_tohoku)
// Condition: Register sake from all 6 Tohoku prefectures
if (!unlockedBadges.contains('regional_tohoku')) {
final tohokuPrefectures = {'青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県'};
final registeredPrefectures = allItems
.map((item) => item.displayData.prefecture)
.where((pref) => tohokuPrefectures.contains(pref))
.toSet();
if (registeredPrefectures.length == 6) {
newlyUnlocked.add(BadgeUnlock('regional_tohoku', '東北制覇', '👹'));
}
}
// 3. Badge: 辛口党 (flavor_dry)
// Condition: Register 10+ sake with SMV >= +5
if (!unlockedBadges.contains('flavor_dry')) {
final dryItems = allItems.where((item) {
final smv = item.hiddenSpecs.sakeMeterValue;
return smv != null && smv >= 5.0;
}).toList();
if (dryItems.length >= 10) {
newlyUnlocked.add(BadgeUnlock('flavor_dry', '辛口党', '🌶️'));
}
}
// 4. Badge: 関東制覇 (regional_kanto)
// Condition: Register sake from all 7 Kanto prefectures
if (!unlockedBadges.contains('regional_kanto')) {
final kantoPrefectures = {'茨城県', '栃木県', '群馬県', '埼玉県', '千葉県', '東京都', '神奈川県'};
final registeredPrefectures = allItems
.map((item) => item.displayData.prefecture)
.where((pref) => kantoPrefectures.contains(pref))
.toSet();
if (registeredPrefectures.length == 7) {
newlyUnlocked.add(BadgeUnlock('regional_kanto', '関東制覇', '🗻'));
}
}
// 5. Badge: 関西制覇 (regional_kansai)
// Condition: Register sake from all 6 Kansai prefectures
if (!unlockedBadges.contains('regional_kansai')) {
final kansaiPrefectures = {'滋賀県', '京都府', '大阪府', '兵庫県', '奈良県', '和歌山県'};
final registeredPrefectures = allItems
.map((item) => item.displayData.prefecture)
.where((pref) => kansaiPrefectures.contains(pref))
.toSet();
if (registeredPrefectures.length == 6) {
newlyUnlocked.add(BadgeUnlock('regional_kansai', '関西制覇', '🏯'));
}
}
// 6. Badge: 愛好家 (collector_10)
// Condition: Register 10+ sake
if (!unlockedBadges.contains('collector_10') && allItems.length >= 10) {
newlyUnlocked.add(BadgeUnlock('collector_10', '愛好家', '🎉'));
}
// 7. Badge: コレクター (collector_50)
// Condition: Register 50+ sake
if (!unlockedBadges.contains('collector_50') && allItems.length >= 50) {
newlyUnlocked.add(BadgeUnlock('collector_50', 'コレクター', '📚'));
}
// 8. Badge: レジェンド (collector_100)
// Condition: Register 100+ sake
if (!unlockedBadges.contains('collector_100') && allItems.length >= 100) {
newlyUnlocked.add(BadgeUnlock('collector_100', 'レジェンド', '👑'));
}
// 9. Badge: 甘口党 (flavor_sweet)
// Condition: Register 10+ sake with SMV <= -3
if (!unlockedBadges.contains('flavor_sweet')) {
final sweetItems = allItems.where((item) {
final smv = item.hiddenSpecs.sakeMeterValue;
return smv != null && smv <= -3.0;
}).toList();
if (sweetItems.length >= 10) {
newlyUnlocked.add(BadgeUnlock('flavor_sweet', '甘口党', '🍯'));
}
}
// 10. Badge: 香りの貴族 (flavor_aromatic)
// Condition: Register 10+ sake with high aroma score (>= 4.0)
if (!unlockedBadges.contains('flavor_aromatic')) {
final aromaticItems = allItems.where((item) {
final tasteStats = item.hiddenSpecs.sakeTasteStats;
return tasteStats.aroma >= 4.0;
}).toList();
if (aromaticItems.length >= 10) {
newlyUnlocked.add(BadgeUnlock('flavor_aromatic', '香りの貴族', '🌸'));
}
}
// Update UserProfile if there are newly unlocked badges
if (newlyUnlocked.isNotEmpty) {
final updatedBadges = [...unlockedBadges, ...newlyUnlocked.map((b) => b.id)];
await ref.read(userProfileProvider.notifier).updateUnlockedBadges(updatedBadges);
}
return newlyUnlocked;
}
}