// lib/game/daily/daily_reward.dart import '../models/booster.dart'; /// The result of evaluating the calendar for "today". class DailyResolution { const DailyResolution({required this.claimable, required this.day}); final bool claimable; final int day; // 1..7, the day to show/grant } /// Pure 7-day login-calendar logic. No storage or clock — callers pass the /// persisted state and today's date so it is fully unit-testable. class DailyRewardCalendar { const DailyRewardCalendar(); static const int cycle = 7; String ymd(DateTime date) { final m = date.month.toString().padLeft(2, '0'); final d = date.day.toString().padLeft(2, '0'); return '${date.year}-$m-$d'; } DailyResolution resolve({ required String? lastClaimedYmd, required int storedDay, required DateTime today, }) { final todayYmd = ymd(today); if (lastClaimedYmd == todayYmd) { return DailyResolution(claimable: false, day: storedDay); } final yesterday = ymd(today.subtract(const Duration(days: 1))); final int day; if (lastClaimedYmd == yesterday) { day = (storedDay % cycle) + 1; // advance, wrapping 7 -> 1 } else { day = 1; // first ever, or a day was missed } return DailyResolution(claimable: true, day: day); } /// Boosters granted for a given calendar day (1..7). Tunable. Map rewardFor(int day) { switch (day) { case 1: return {BoosterType.hammer: 1}; case 2: return {BoosterType.shuffle: 1}; case 3: return {BoosterType.lineBomb: 1}; case 4: return {BoosterType.hammer: 1, BoosterType.shuffle: 1}; case 5: return {BoosterType.shuffle: 1, BoosterType.lineBomb: 1}; case 6: return {BoosterType.hammer: 1, BoosterType.lineBomb: 1}; case 7: default: return { BoosterType.hammer: 2, BoosterType.shuffle: 2, BoosterType.lineBomb: 2, }; } } }