积分、成就系统
This commit is contained in:
144
lib/models/user_progress.dart
Normal file
144
lib/models/user_progress.dart
Normal file
@@ -0,0 +1,144 @@
|
||||
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<String, DateTime> unlockedAchievements;
|
||||
|
||||
@HiveField(5)
|
||||
int totalFocusMinutes;
|
||||
|
||||
@HiveField(6)
|
||||
int totalDistractions;
|
||||
|
||||
@HiveField(7)
|
||||
int totalSessions;
|
||||
|
||||
@HiveField(8)
|
||||
List<DateTime> checkInHistory;
|
||||
|
||||
UserProgress({
|
||||
this.totalPoints = 0,
|
||||
this.currentPoints = 0,
|
||||
this.lastCheckInDate,
|
||||
this.consecutiveCheckIns = 0,
|
||||
Map<String, DateTime>? unlockedAchievements,
|
||||
this.totalFocusMinutes = 0,
|
||||
this.totalDistractions = 0,
|
||||
this.totalSessions = 0,
|
||||
List<DateTime>? 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<DateTime>.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<int> 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];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user