from datetime import datetime, timedelta, timezone def calculate_next_review(box_level: int) -> datetime: intervals = { 1: 1, 2: 3, 3: 7, 4: 14, 5: 30 } days = intervals.get(box_level, 1) return datetime.now(timezone.utc) + timedelta(days=days) def evaluate_new_box(current_box: int, rating: str) -> int: """ rating: "Correct", "Mixed", "Incorrect" """ if rating == "Correct": return min(current_box + 1, 5) elif rating == "Mixed": return current_box else: # Incorrect return 1 def lazy_check_streak(streak_data): """ Evaluates streak on Login (lazy checking). Resets to 0 if the user missed a day. """ if not streak_data.get('last_active_date'): return streak_data now = datetime.now(timezone.utc) current_date = now.date() last_active_date = datetime.strptime(streak_data['last_active_date'], '%Y-%m-%d').date() delta = (current_date - last_active_date).days if delta > 1: streak_data['current_streak'] = 0 return streak_data def increment_streak(streak_data): """ Updates the streak object when a practice session is completed. """ now = datetime.now(timezone.utc) current_date = now.date() last_active = streak_data.get('last_active_date') if last_active: last_active_date = datetime.strptime(last_active, '%Y-%m-%d').date() delta = (current_date - last_active_date).days else: delta = 2 # force increment for first time if delta == 1 or last_active is None: streak_data['current_streak'] += 1 streak_data['longest_streak'] = max(streak_data['longest_streak'], streak_data['current_streak']) elif delta > 1: # Restarting streak streak_data['current_streak'] = 1 streak_data['longest_streak'] = max(streak_data['longest_streak'], streak_data['current_streak']) streak_data['last_active_date'] = current_date.isoformat() return streak_data