-- Reads memory keys "habit_streak.." and computes streak per habit. local t = jarvis.context.time local function date_offset(days_back) -- Simple naive backwards calc (no calendar arithmetic — close enough for streaks) local jd_today = t.year * 365 + math.floor(t.year / 4) + ({0,31,59,90,120,151,181,212,243,273,304,334})[t.month] + (t.day - 1) local target_jd = jd_today - days_back -- Convert back to YYYY-MM-DD (approximate) local y = math.floor(target_jd / 365.25) local doy = target_jd - math.floor(y * 365.25) local month_starts = {0,31,59,90,120,151,181,212,243,273,304,334} local mo = 12 for i = 12, 1, -1 do if doy >= month_starts[i] then mo = i; doy = doy - month_starts[i]; break end end return string.format("%04d-%02d-%02d", y, mo, doy + 1) end local all = jarvis.memory.all() -- Group keys by habit name local by_habit = {} for _, rec in ipairs(all) do local habit, date = rec.key:match("^habit_streak%.([^%.]+)%.(.+)$") if habit and date then by_habit[habit] = by_habit[habit] or {} by_habit[habit][date] = true end end if next(by_habit) == nil then return jarvis.cmd.not_found("Привычек ещё не отмечено. Скажи 'выполнил привычку' после события.") end -- For each habit, count consecutive days back from today local results = {} for habit, dates in pairs(by_habit) do local streak = 0 for d = 0, 30 do local key_date = date_offset(d) if dates[key_date] then streak = streak + 1 else break end end table.insert(results, { habit = habit, streak = streak }) end table.sort(results, function(a, b) return a.streak > b.streak end) local sample = math.min(#results, 3) local lines = {} for i = 1, sample do local r = results[i] if r.streak == 0 then table.insert(lines, r.habit .. " прервана") else local d = r.streak == 1 and "день" or (r.streak < 5 and "дня" or "дней") table.insert(lines, r.habit .. " " .. r.streak .. " " .. d) end end return jarvis.cmd.ok("Стрики: " .. table.concat(lines, ", ") .. ".")