J.A.R.V.I.S-rust/resources/commands/habit_streaks/streak.lua

67 lines
2.2 KiB
Lua
Raw Normal View History

feat: Wave 1 — 10 new packs (75 → 85 rust packs) User picked from the fishki roadmap; this commit ships the 10 easy/medium ones in one batch. No Rust core changes — all pure Lua + jarvis.* APIs. Pack catalog magic_8ball - "ответь да или нет" / "магический шар" / "что скажешь" - 15 канонических ответов, random pick. Pure fun. github_issues (2 cmds) - "какие issues" / "открытые issues" — gh issue list по сохранённому репо - "мои issues" / "что мне назначено" — gh issue list --assignee @me weather_extended (2 cmds, Open-Meteo, no key) - "погода завтра" — temp min/max + conditions + rain note - "прогноз на неделю" — общий диапазон температур - Auto-detects location via ipinfo.io if not in memory; stores lat/lon/city. rss_reader (3 cmds) - "добавь rss <url>" — extracts URL, persists via memory под ключом "rss.<domain>" - "что в ленте" — fetches first feed, parses <title> tags, speaks top 3 - "какие у меня rss" — lists subscribed feed domains ics_event - "добавь встречу завтра в 15:00 обсудить проект" - Parses time (HH:MM или "в HH") + date keywords (сегодня/завтра/послезавтра) - Writes valid iCalendar v2.0 file to ~/Documents/jarvis-events/ - jarvis.system.open → дефолтный handler (Outlook/Mail/whatever) backup - "сделай бекап" — PowerShell Compress-Archive всех state files из APPDATA/Jarvis - Outputs to ~/Documents/jarvis-backup-<YYYYMMDD-HHMMSS>.zip - Bundles: long_term_memory, schedule, macros, profiles/, active_profile, llm_backend, settings clip_history (3 cmds, 20-slot rolling buffer) - "запиши буфер" — push current clipboard onto memory keys clip.0..clip.19 - "что я копировал" — speak preview of last 3 - "верни первый/второй/третий буфер" — restore clip.N to clipboard notif_queue (2 cmds) - "что я пропустил" — enumerate memory keys "notif.*", speak last 5 by recency - "очисти уведомления" — purge all notif.* keys - Producers (scheduler/macros/llm) can later push to memory[notif.<ts>] = text password_vault (3 cmds, Windows DPAPI) - "сохрани пароль от GitHub" — encrypts current clipboard content via DPAPI (CurrentUser scope), base64-stored in memory[vault.GitHub]. Clears clipboard. Password is NEVER spoken or written to disk in plaintext. - "пароль от GitHub" — decrypts via DPAPI, restores to clipboard for 30 sec, schedules auto-clear via jarvis.scheduler. Speaks only "Пароль от X в буфере." - "какие у меня пароли" — list of stored service names. habit_streaks (2 cmds, integrates with habit_nudge) - "сколько дней подряд" / "статистика привычек" — reads memory keys "habit_streak.<habit>.<YYYY-MM-DD>", computes consecutive-day streak per habit. - "я попил воды" / "отметь привычку" — marks today's check-in. Maps voice to habit: воды→water, размял/зарядк→stretch, глаз→eyes. Tests: 6 commands tests pass (auto-validate the 10 new packs).
2026-05-16 01:04:23 +03:00
-- Reads memory keys "habit_streak.<habit>.<YYYY-MM-DD>" 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, ", ") .. ".")