137 lines
3.5 KiB
Python
Executable File
137 lines
3.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
streak - View all streaks across tools
|
|
|
|
Unified view of habit streaks, journal streaks, etc.
|
|
"""
|
|
|
|
import json
|
|
from datetime import datetime, timedelta
|
|
from pathlib import Path
|
|
|
|
WORKSPACE = Path("/home/wdjones/.openclaw/workspace")
|
|
|
|
def load_json(path: Path):
|
|
if path.exists():
|
|
try:
|
|
with open(path) as f:
|
|
return json.load(f)
|
|
except:
|
|
pass
|
|
return {}
|
|
|
|
def check_date_exists(data: dict | list, date: str, key: str = None) -> bool:
|
|
"""Check if an entry exists for a date."""
|
|
if isinstance(data, dict):
|
|
if key:
|
|
return date in data.get(key, {})
|
|
return date in data
|
|
return False
|
|
|
|
def calculate_streak(check_func) -> int:
|
|
"""Calculate a streak based on a check function."""
|
|
streak = 0
|
|
date = datetime.now()
|
|
|
|
while True:
|
|
date_str = date.strftime("%Y-%m-%d")
|
|
if check_func(date_str):
|
|
streak += 1
|
|
date -= timedelta(days=1)
|
|
else:
|
|
break
|
|
|
|
return streak
|
|
|
|
def get_habit_streak(habit_name: str) -> int:
|
|
"""Get streak for a habit."""
|
|
data = load_json(WORKSPACE / "data" / "habits.json")
|
|
log = data.get('log', {})
|
|
|
|
def check(date):
|
|
return habit_name in log.get(date, [])
|
|
|
|
return calculate_streak(check)
|
|
|
|
def get_journal_streak() -> int:
|
|
"""Get journal writing streak."""
|
|
journal_dir = WORKSPACE / "journal"
|
|
if not journal_dir.exists():
|
|
return 0
|
|
|
|
def check(date):
|
|
year, month, day = date.split('-')
|
|
path = journal_dir / year / month / f"{date}.json"
|
|
if path.exists():
|
|
data = load_json(path)
|
|
return len(data.get('entries', [])) > 0
|
|
return False
|
|
|
|
return calculate_streak(check)
|
|
|
|
def get_notes_streak() -> int:
|
|
"""Get daily notes streak."""
|
|
memory_dir = WORKSPACE / "memory"
|
|
if not memory_dir.exists():
|
|
return 0
|
|
|
|
def check(date):
|
|
path = memory_dir / f"{date}.md"
|
|
return path.exists()
|
|
|
|
return calculate_streak(check)
|
|
|
|
def get_time_tracking_streak() -> int:
|
|
"""Get time tracking streak."""
|
|
data = load_json(WORKSPACE / "data" / "timetrack.json")
|
|
entries = data.get('entries', [])
|
|
|
|
dates_tracked = set()
|
|
for e in entries:
|
|
date = e['start'][:10]
|
|
dates_tracked.add(date)
|
|
|
|
def check(date):
|
|
return date in dates_tracked
|
|
|
|
return calculate_streak(check)
|
|
|
|
def show_streaks():
|
|
"""Show all streaks."""
|
|
print("\n🔥 Streaks")
|
|
print("=" * 40)
|
|
|
|
# Notes streak
|
|
notes = get_notes_streak()
|
|
print(f" 📝 Daily Notes: {notes} day{'s' if notes != 1 else ''}")
|
|
|
|
# Journal streak
|
|
journal = get_journal_streak()
|
|
print(f" 📔 Journal: {journal} day{'s' if journal != 1 else ''}")
|
|
|
|
# Time tracking streak
|
|
time_track = get_time_tracking_streak()
|
|
print(f" ⏱️ Time Tracking: {time_track} day{'s' if time_track != 1 else ''}")
|
|
|
|
# Habit streaks
|
|
habits_data = load_json(WORKSPACE / "data" / "habits.json")
|
|
habits = habits_data.get('habits', {})
|
|
|
|
if habits:
|
|
print(f"\n 📊 Habits:")
|
|
for name, info in habits.items():
|
|
if info.get('active', True):
|
|
streak = get_habit_streak(name)
|
|
if streak > 0:
|
|
print(f" {name}: {streak} day{'s' if streak != 1 else ''} 🔥")
|
|
else:
|
|
print(f" {name}: 0 days")
|
|
|
|
print()
|
|
|
|
def main():
|
|
show_streaks()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|