| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- import 'package:shared_preferences/shared_preferences.dart';
- import 'dart:convert';
- class ScoreManager {
- static const String _todayScoreKey = 'today_score';
- static const String _totalScoreKey = 'total_score';
- static const String _dailyHistoryKey = 'daily_history';
- static const String _lastDateKey = 'last_date';
- static int _todayScore = 0;
- static int _totalScore = 0;
- static Map<String, int> _dailyHistory = {};
- static int get todayScore => _todayScore;
- static int get totalScore => _totalScore;
- static Map<String, int> get dailyHistory => Map.from(_dailyHistory);
- /// Initialize the score manager - loads saved data
- static Future<void> initialize() async {
- await _loadScores();
- await _checkNewDay();
- }
- /// Add points to today's score
- static Future<void> addScore(int points) async {
- _todayScore += points;
- _totalScore += points;
- await _saveScores();
- }
- /// Reset today's score (for testing purposes)
- static Future<void> resetTodayScore() async {
- _todayScore = 0;
- await _saveScores();
- }
- /// Get scores for the last N days (for charts)
- static List<MapEntry<String, int>> getLastDaysScores(int days) {
- final now = DateTime.now();
- final result = <MapEntry<String, int>>[];
- for (int i = days - 1; i >= 0; i--) {
- final date = now.subtract(Duration(days: i));
- final dateStr = _formatDate(date);
- final score = _dailyHistory[dateStr] ?? 0;
- result.add(MapEntry(dateStr, score));
- }
- return result;
- }
- /// Get weekly totals for the last N weeks
- static List<MapEntry<String, int>> getWeeklyScores(int weeks) {
- final now = DateTime.now();
- final result = <MapEntry<String, int>>[];
- for (int i = weeks - 1; i >= 0; i--) {
- final weekStart = now.subtract(Duration(days: now.weekday - 1 + (i * 7)));
-
- int weekTotal = 0;
- for (int day = 0; day < 7; day++) {
- final date = weekStart.add(Duration(days: day));
- final dateStr = _formatDate(date);
- weekTotal += _dailyHistory[dateStr] ?? 0;
- }
- final weekLabel = 'Week of ${_formatDate(weekStart)}';
- result.add(MapEntry(weekLabel, weekTotal));
- }
- return result;
- }
- /// Get total bubbles popped (approximate based on score)
- static int get totalBubblesPopped => _totalScore ~/ 10; // 10 points per bubble
- /// Get average daily score
- static double get averageDailyScore {
- if (_dailyHistory.isEmpty) return 0.0;
- final total = _dailyHistory.values.fold(0, (a, b) => a + b);
- return total / _dailyHistory.length;
- }
- /// Get current streak (consecutive days with score > 0)
- static int get currentStreak {
- final now = DateTime.now();
- int streak = 0;
- for (int i = 0; i < 365; i++) { // Check up to a year
- final date = now.subtract(Duration(days: i));
- final dateStr = _formatDate(date);
- final score = _dailyHistory[dateStr] ?? 0;
- if (score > 0) {
- streak++;
- } else {
- break;
- }
- }
- return streak;
- }
- /// Get best day score
- static int get bestDayScore {
- if (_dailyHistory.isEmpty) return _todayScore;
- return _dailyHistory.values.fold(_todayScore, (a, b) => a > b ? a : b);
- }
- static Future<void> _loadScores() async {
- final prefs = await SharedPreferences.getInstance();
-
- // Handle potential type mismatches from previous versions
- try {
- _todayScore = prefs.getInt(_todayScoreKey) ?? 0;
- } catch (e) {
- // Clean up corrupted data
- await prefs.remove(_todayScoreKey);
- _todayScore = 0;
- }
-
- try {
- _totalScore = prefs.getInt(_totalScoreKey) ?? 0;
- } catch (e) {
- // Clean up corrupted data
- await prefs.remove(_totalScoreKey);
- _totalScore = 0;
- }
-
- final historyJson = prefs.getString(_dailyHistoryKey) ?? '{}';
- try {
- final historyMap = json.decode(historyJson) as Map<String, dynamic>;
- _dailyHistory = historyMap.map((key, value) => MapEntry(key, value as int));
- } catch (e) {
- _dailyHistory = {};
- // Clean up corrupted data
- await prefs.remove(_dailyHistoryKey);
- }
- }
- static Future<void> _saveScores() async {
- final prefs = await SharedPreferences.getInstance();
-
- await prefs.setInt(_todayScoreKey, _todayScore);
- await prefs.setInt(_totalScoreKey, _totalScore);
- await prefs.setString(_lastDateKey, DateTime.now().toIso8601String().split('T')[0]);
-
- // Save today's score to history
- final today = _formatDate(DateTime.now());
- _dailyHistory[today] = _todayScore;
-
- final historyJson = json.encode(_dailyHistory);
- await prefs.setString(_dailyHistoryKey, historyJson);
- }
- static Future<void> _checkNewDay() async {
- final prefs = await SharedPreferences.getInstance();
- final lastDate = prefs.getString(_lastDateKey);
- final today = _formatDate(DateTime.now());
- if (lastDate != today) {
- // New day - save yesterday's score and reset today's
- if (lastDate != null && _todayScore > 0) {
- _dailyHistory[lastDate] = _todayScore;
- }
- _todayScore = 0;
- await prefs.setString(_lastDateKey, today);
- await _saveScores();
- }
- }
- static String _formatDate(DateTime date) {
- return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
- }
- /// Clean up old data (keep only last 365 days)
- static Future<void> cleanupOldData() async {
- final cutoffDate = DateTime.now().subtract(const Duration(days: 365));
- final cutoffStr = _formatDate(cutoffDate);
- _dailyHistory.removeWhere((date, score) => date.compareTo(cutoffStr) < 0);
- await _saveScores();
- }
- }
|