|
| 1 | +import type { MoodLog } from '../models/mood'; |
| 2 | + |
| 3 | +export type WeeklyInsight = { |
| 4 | + metric: 'avg_mood' | 'avg_energy' | 'mood_trend' | 'suggestion'; |
| 5 | + value: number; |
| 6 | + note?: string; |
| 7 | +}; |
| 8 | + |
| 9 | +function average(values: number[]): number { |
| 10 | + if (values.length === 0) return 0; |
| 11 | + return values.reduce((s, n) => s + n, 0) / values.length; |
| 12 | +} |
| 13 | + |
| 14 | +export function computeWeeklyInsights(moods: MoodLog[], windowDays = 7): WeeklyInsight[] { |
| 15 | + if (!moods || moods.length === 0) return []; |
| 16 | + const byDate = [...moods].sort((a, b) => a.date.localeCompare(b.date)); |
| 17 | + const recent = byDate.slice(-windowDays); |
| 18 | + const avgMood = average(recent.map((m) => m.mood)); |
| 19 | + const avgEnergy = average(recent.map((m) => m.energy)); |
| 20 | + const trend = (recent.at(-1)?.mood ?? 0) - (recent[0]?.mood ?? 0); |
| 21 | + |
| 22 | + const insights: WeeklyInsight[] = [ |
| 23 | + { metric: 'avg_mood', value: Number(avgMood.toFixed(2)) }, |
| 24 | + { metric: 'avg_energy', value: Number(avgEnergy.toFixed(2)) }, |
| 25 | + { metric: 'mood_trend', value: Number(trend.toFixed(2)) } |
| 26 | + ]; |
| 27 | + |
| 28 | + // Gentle suggestions |
| 29 | + if (avgMood <= 4) { |
| 30 | + insights.push({ metric: 'suggestion', value: 1, note: 'Consider reducing planned load and adding more recovery time this week.' }); |
| 31 | + } |
| 32 | + if (trend <= -2) { |
| 33 | + insights.push({ metric: 'suggestion', value: 1, note: 'Mood trend is down. Try shorter deep blocks or fewer per day.' }); |
| 34 | + } |
| 35 | + if (avgEnergy <= 4.5) { |
| 36 | + insights.push({ metric: 'suggestion', value: 1, note: 'Energy is low. Schedule movement breaks and lighter tasks after lunch.' }); |
| 37 | + } |
| 38 | + if (insights.filter((i) => i.metric === 'suggestion').length === 0) { |
| 39 | + insights.push({ metric: 'suggestion', value: 1, note: 'You seem stable. Maintain buffers and keep protecting sleep and breaks.' }); |
| 40 | + } |
| 41 | + return insights; |
| 42 | +} |
| 43 | + |
| 44 | + |
0 commit comments