AgentSkillsCN

streaks-stats-gamification

TryRamadan 中的禁食连续天数、豁免天数、非禁食成就(日记、正念饮食),以及连续禁食与成就的切换功能。适用于调整连续禁食的计算逻辑、勋章系统、showStreakAndAchievements 设置,或依赖于“已完成/中断/跳过”状态的各类统计指标时使用。

SKILL.md
--- frontmatter
name: streaks-stats-gamification
description: Fasting streaks, excused days, non-fasting achievements (journal, mindful eating), and streak/achievement toggle in TryRamadan. Use when changing streak calculation, badges, showStreakAndAchievements, or stats that depend on completed/broken/skipped.

Streaks, Stats, and Gamification (TryRamadan)

Use this skill when changing streak logic, badges, excused vs non-excused, or the "Show streak and achievements" preference so behavior and copy stay consistent with the documented flows.


1. Fasting streak

  • Definition: Consecutive calendar days ending on "today" where each day is either completed (full fast) or broken with excused reason (illness, travel, menstruation, medical). Excused days do not break the streak; they extend it.
  • Helpers: getStreakDays(progress, todayOverride?), calculateStreak(progress, todayOverride?) in src/hooks/useLocalStorage.ts. Pass todayOverride (e.g. from display timezone) so streak uses the same "today" as the rest of the app (see ramadan-calendar-and-fasting-logic skill).
  • Breaking the streak: Skipped day ("I didn't fast today"), broken with non-excused reason (e.g. "Ate by mistake", "Other"), or day left untracked — streak resets when looking backward from today.
  • Copy: Neutral, no guilt. Tooltip: "Consecutive days you completed the full fast or had an excused break (e.g. illness, travel). Excused days don't reset your streak — that's okay."

2. Excused reasons

  • IDs: ['illness','travel','menstruation','medical']. Stored in fastingLog as brokenReason. Used by getExcusedFastDays(progress); streak and longest-streak calculations treat these as streak-preserving.
  • Longest streak: getLongestStreak(progress) — longest run of consecutive days where each is completed or excused (any order).

3. Non-fasting achievements

  • Journal streak: Consecutive days (ending today) with at least one journal entry — getJournalStreak(entries).
  • Mindful eating streak: Consecutive days with both suhoor and iftar logged — getMindfulEatingStreak(foodLogs, mealPlans).
  • UI: Progress page shows "Non-fasting wins" (journal streak, both meals logged) when present. Badges (streak-5, streak-10, etc.) and "Current streak" / "Badges" sections respect showStreakAndAchievements.

4. Preference: Show streak and achievements

  • Key: preferences.showStreakAndAchievements (default true). When false, Dashboard hides streak card and milestone celebration; Progress hides Current streak, Longest streak, and Badges section; Settings still shows streak in "Data Management" preview.
  • Data: Toggling this preference does not change progress or streak calculation; it only hides/shows UI. Streak must use same "today" as Dashboard (todayOverride) to avoid showing 0 after toggle (see Regression: BUG-STRK-001).

5. Tests and doc

  • Tests: src/test/loggingAndTracking.test.ts (streak, excused days, todayOverride); Regression: BUG-STRK-001.
  • Doc: docs/STREAKS-STATS-GAMIFICATION-FLOWS.md (building/breaking streak, copy tone, disabling streak, non-fasting wins).