import 'package:hive/hive.dart'; part 'user_progress.g.dart'; @HiveType(typeId: 1) class UserProgress extends HiveObject { @HiveField(0) int totalPoints; @HiveField(1) int currentPoints; @HiveField(2) DateTime? lastCheckInDate; @HiveField(3) int consecutiveCheckIns; @HiveField(4) Map unlockedAchievements; @HiveField(5) int totalFocusMinutes; @HiveField(6) int totalDistractions; @HiveField(7) int totalSessions; @HiveField(8) List checkInHistory; UserProgress({ this.totalPoints = 0, this.currentPoints = 0, this.lastCheckInDate, this.consecutiveCheckIns = 0, Map? unlockedAchievements, this.totalFocusMinutes = 0, this.totalDistractions = 0, this.totalSessions = 0, List? checkInHistory, }) : unlockedAchievements = unlockedAchievements ?? {}, checkInHistory = checkInHistory ?? []; /// Get current level based on total points int get level { return LevelSystem.getLevel(totalPoints); } /// Get progress to next level (0.0 - 1.0) double get levelProgress { return LevelSystem.getLevelProgress(totalPoints); } /// Get points needed to reach next level int get pointsToNextLevel { return LevelSystem.getPointsToNextLevel(totalPoints); } /// Check if checked in today bool get hasCheckedInToday { if (lastCheckInDate == null) return false; final now = DateTime.now(); return lastCheckInDate!.year == now.year && lastCheckInDate!.month == now.month && lastCheckInDate!.day == now.day; } /// Get longest check-in streak from history int get longestCheckInStreak { if (checkInHistory.isEmpty) return 0; int maxStreak = 1; int currentStreak = 1; // Sort dates final sortedDates = List.from(checkInHistory) ..sort((a, b) => a.compareTo(b)); for (int i = 1; i < sortedDates.length; i++) { final diff = sortedDates[i].difference(sortedDates[i - 1]).inDays; if (diff == 1) { currentStreak++; maxStreak = currentStreak > maxStreak ? currentStreak : maxStreak; } else { currentStreak = 1; } } return maxStreak; } } /// Level system configuration class LevelSystem { static const List levelThresholds = [ 0, // Level 0 → 1: 0 points 50, // Level 1 → 2: 50 points 150, // Level 2 → 3: 150 points 300, // Level 3 → 4: 300 points 500, // Level 4 → 5: 500 points 800, // Level 5 → 6: 800 points 1200, // Level 6 → 7: 1200 points 1800, // Level 7 → 8: 1800 points 2500, // Level 8 → 9: 2500 points 3500, // Level 9 → 10: 3500 points ]; static int getLevel(int points) { for (int i = levelThresholds.length - 1; i >= 0; i--) { if (points >= levelThresholds[i]) { return i; } } return 0; } static double getLevelProgress(int points) { int currentLevel = getLevel(points); if (currentLevel >= levelThresholds.length - 1) return 1.0; int currentThreshold = levelThresholds[currentLevel]; int nextThreshold = levelThresholds[currentLevel + 1]; return (points - currentThreshold) / (nextThreshold - currentThreshold); } static int getPointsToNextLevel(int points) { int currentLevel = getLevel(points); if (currentLevel >= levelThresholds.length - 1) return 0; return levelThresholds[currentLevel + 1] - points; } static int getNextLevelThreshold(int points) { int currentLevel = getLevel(points); if (currentLevel >= levelThresholds.length - 1) { return levelThresholds.last; } return levelThresholds[currentLevel + 1]; } }