core/utils/smart_reminder_scheduling library

Constants

kEnergyReminderNotificationId → const int
ReminderService.scheduleNext/ReminderService.cancel id for the energy-full reminder scheduled by rescheduleEnergyReminder — distinct from ReminderService's own default id: 0 slot and from kStreakReminderNotificationId, so all 3 coexist as independent notifications.
kStreakReminderNotificationId → const int
ReminderService.scheduleNext/ReminderService.cancel id for the streak-expiring reminder scheduled by rescheduleStreakReminder.

Functions

energyFullReminderDelay(EnergyService energy) → Duration?
How long until energy's bar is completely full (null if it already is, or EnergyService.hasInfiniteLives is active — no reminder is useful in either case). Pure function of energy's own already-tested getters (EnergyService.currentEnergy/EnergyService.timeUntilNextEnergy), not a new regen formula — EnergyService.timeUntilNextEnergy alone only answers "until the NEXT point", so this adds the remaining whole ticks after that on top.
rescheduleEnergyReminder({required EnergyService energy, required ReminderService reminder, String title = 'Năng lượng đã đầy!', String body = 'Quay lại chơi ngay để không lãng phí năng lượng.'}) → Future<void>
Re-derives the energy-full reminder from energy's CURRENT state and (re)schedules it via reminder at kEnergyReminderNotificationId — or cancels that slot if no reminder is currently useful (already full, or infinite lives active). Call this again any time energy state changes (after consumeEnergy, after grantInfiniteLives, on app resume) so a stale schedule never outlives the state it was computed from (IDEA-62's AC3) — this coordinator has no way to observe those changes on its own, by design (no new cross-service event bus for something a caller can just call directly at the right hooks).
rescheduleStreakReminder({required DailyLoginService dailyLogin, required ReminderService reminder, Duration warnBefore = const Duration(hours: 4), String title = 'Đừng để mất streak!', String body = 'Streak điểm danh của bạn sắp hết hạn hôm nay.'}) → Future<void>
Re-derives the streak-expiring reminder from dailyLogin's CURRENT state and (re)schedules it via reminder at kStreakReminderNotificationId — or cancels that slot if today's reward is already claimed. Call this again any time login-streak state changes (after claimToday, on app resume) for the same reason rescheduleEnergyReminder's own doc explains.
streakExpiringReminderDelay(DailyLoginService dailyLogin, {Duration warnBefore = const Duration(hours: 4)}) → Duration
How long until a reminder should fire warning the player their dailyLogin streak is about to lapse — null if today's reward is already claimed (the streak is safe, no reminder needed).