Fix AI insights data calculations
- Change mood scale from 0-4 to 1-5 for human-readable averages (Horrible=1, Bad=2, Average=3, Good=4, Great=5) - Fix streak calculation to check consecutive calendar days, not just consecutive entries in array - Update prompt to show /5 scale instead of /4 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -116,7 +116,8 @@ class MoodDataSummarizer {
|
|||||||
for entry in entries {
|
for entry in entries {
|
||||||
let moodName = entry.mood.widgetDisplayName.lowercased()
|
let moodName = entry.mood.widgetDisplayName.lowercased()
|
||||||
counts[moodName, default: 0] += 1
|
counts[moodName, default: 0] += 1
|
||||||
totalScore += Int(entry.moodValue)
|
// Use 1-5 scale (add 1 to raw 0-4 values) for human-readable averages
|
||||||
|
totalScore += Int(entry.moodValue) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
var percentages: [String: Int] = [:]
|
var percentages: [String: Int] = [:]
|
||||||
@@ -138,14 +139,15 @@ class MoodDataSummarizer {
|
|||||||
for entry in entries {
|
for entry in entries {
|
||||||
let weekday = Int(entry.weekDay)
|
let weekday = Int(entry.weekDay)
|
||||||
let current = weekdayTotals[weekday, default: (0, 0)]
|
let current = weekdayTotals[weekday, default: (0, 0)]
|
||||||
weekdayTotals[weekday] = (current.total + Int(entry.moodValue), current.count + 1)
|
// Use 1-5 scale (add 1 to raw 0-4 values)
|
||||||
|
weekdayTotals[weekday] = (current.total + Int(entry.moodValue) + 1, current.count + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
var weekdayAverages: [String: Double] = [:]
|
var weekdayAverages: [String: Double] = [:]
|
||||||
var bestDay = "Monday"
|
var bestDay = "Monday"
|
||||||
var worstDay = "Monday"
|
var worstDay = "Monday"
|
||||||
var bestAvg = -1.0
|
var bestAvg = -1.0
|
||||||
var worstAvg = 5.0
|
var worstAvg = 6.0
|
||||||
|
|
||||||
for (weekday, data) in weekdayTotals {
|
for (weekday, data) in weekdayTotals {
|
||||||
let avg = Double(data.total) / Double(data.count)
|
let avg = Double(data.total) / Double(data.count)
|
||||||
@@ -162,12 +164,12 @@ class MoodDataSummarizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Weekend vs weekday
|
// Weekend vs weekday (use 1-5 scale)
|
||||||
let weekendEntries = entries.filter { [1, 7].contains(Int($0.weekDay)) }
|
let weekendEntries = entries.filter { [1, 7].contains(Int($0.weekDay)) }
|
||||||
let weekdayEntries = entries.filter { ![1, 7].contains(Int($0.weekDay)) }
|
let weekdayEntries = entries.filter { ![1, 7].contains(Int($0.weekDay)) }
|
||||||
|
|
||||||
let weekendAvg = weekendEntries.isEmpty ? 0 : Double(weekendEntries.reduce(0) { $0 + Int($1.moodValue) }) / Double(weekendEntries.count)
|
let weekendAvg = weekendEntries.isEmpty ? 0 : Double(weekendEntries.reduce(0) { $0 + Int($1.moodValue) + 1 }) / Double(weekendEntries.count)
|
||||||
let weekdayAvg = weekdayEntries.isEmpty ? 0 : Double(weekdayEntries.reduce(0) { $0 + Int($1.moodValue) }) / Double(weekdayEntries.count)
|
let weekdayAvg = weekdayEntries.isEmpty ? 0 : Double(weekdayEntries.reduce(0) { $0 + Int($1.moodValue) + 1 }) / Double(weekdayEntries.count)
|
||||||
|
|
||||||
return (weekdayAverages, weekendAvg, weekdayAvg, bestDay, worstDay)
|
return (weekdayAverages, weekendAvg, weekdayAvg, bestDay, worstDay)
|
||||||
}
|
}
|
||||||
@@ -183,8 +185,9 @@ class MoodDataSummarizer {
|
|||||||
let firstHalf = Array(entries.prefix(halfCount))
|
let firstHalf = Array(entries.prefix(halfCount))
|
||||||
let secondHalf = Array(entries.suffix(halfCount))
|
let secondHalf = Array(entries.suffix(halfCount))
|
||||||
|
|
||||||
let firstAvg = Double(firstHalf.reduce(0) { $0 + Int($1.moodValue) }) / Double(firstHalf.count)
|
// Use 1-5 scale
|
||||||
let secondAvg = Double(secondHalf.reduce(0) { $0 + Int($1.moodValue) }) / Double(secondHalf.count)
|
let firstAvg = Double(firstHalf.reduce(0) { $0 + Int($1.moodValue) + 1 }) / Double(firstHalf.count)
|
||||||
|
let secondAvg = Double(secondHalf.reduce(0) { $0 + Int($1.moodValue) + 1 }) / Double(secondHalf.count)
|
||||||
|
|
||||||
let diff = secondAvg - firstAvg
|
let diff = secondAvg - firstAvg
|
||||||
|
|
||||||
@@ -252,16 +255,39 @@ class MoodDataSummarizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func calculateMoodStreak(entries: [MoodEntryModel], moods: [Mood]) -> Int {
|
private func calculateMoodStreak(entries: [MoodEntryModel], moods: [Mood]) -> Int {
|
||||||
|
guard !entries.isEmpty else { return 0 }
|
||||||
|
|
||||||
|
// Sort by date to ensure proper ordering
|
||||||
|
let sortedEntries = entries.sorted { $0.forDate < $1.forDate }
|
||||||
|
|
||||||
var longest = 0
|
var longest = 0
|
||||||
var current = 0
|
var current = 0
|
||||||
|
var previousDate: Date?
|
||||||
|
|
||||||
|
for entry in sortedEntries {
|
||||||
|
let entryDate = calendar.startOfDay(for: entry.forDate)
|
||||||
|
|
||||||
|
// Check if this is a consecutive calendar day from the previous entry
|
||||||
|
let isConsecutive: Bool
|
||||||
|
if let prevDate = previousDate {
|
||||||
|
let dayDiff = calendar.dateComponents([.day], from: prevDate, to: entryDate).day ?? 0
|
||||||
|
isConsecutive = dayDiff == 1
|
||||||
|
} else {
|
||||||
|
isConsecutive = true // First entry starts a potential streak
|
||||||
|
}
|
||||||
|
|
||||||
for entry in entries {
|
|
||||||
if moods.contains(entry.mood) {
|
if moods.contains(entry.mood) {
|
||||||
current += 1
|
if isConsecutive || previousDate == nil {
|
||||||
|
current += 1
|
||||||
|
} else {
|
||||||
|
current = 1 // Reset to 1 (this entry starts new streak)
|
||||||
|
}
|
||||||
longest = max(longest, current)
|
longest = max(longest, current)
|
||||||
} else {
|
} else {
|
||||||
current = 0
|
current = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
previousDate = entryDate
|
||||||
}
|
}
|
||||||
|
|
||||||
return longest
|
return longest
|
||||||
@@ -297,7 +323,8 @@ class MoodDataSummarizer {
|
|||||||
return (0, [])
|
return (0, [])
|
||||||
}
|
}
|
||||||
|
|
||||||
let average = Double(recentEntries.reduce(0) { $0 + Int($1.moodValue) }) / Double(recentEntries.count)
|
// Use 1-5 scale
|
||||||
|
let average = Double(recentEntries.reduce(0) { $0 + Int($1.moodValue) + 1 }) / Double(recentEntries.count)
|
||||||
let moods = recentEntries.map { $0.mood.widgetDisplayName }
|
let moods = recentEntries.map { $0.mood.widgetDisplayName }
|
||||||
|
|
||||||
return (average, moods)
|
return (average, moods)
|
||||||
@@ -363,7 +390,7 @@ class MoodDataSummarizer {
|
|||||||
// Compact format to stay under token limit
|
// Compact format to stay under token limit
|
||||||
var lines: [String] = []
|
var lines: [String] = []
|
||||||
|
|
||||||
lines.append("Period: \(summary.periodName), \(summary.totalEntries) entries, avg \(String(format: "%.1f", summary.averageMoodScore))/4")
|
lines.append("Period: \(summary.periodName), \(summary.totalEntries) entries, avg \(String(format: "%.1f", summary.averageMoodScore))/5")
|
||||||
|
|
||||||
// Mood distribution - compact
|
// Mood distribution - compact
|
||||||
let moodDist = summary.moodPercentages.sorted { $0.key < $1.key }
|
let moodDist = summary.moodPercentages.sorted { $0.key < $1.key }
|
||||||
|
|||||||
Reference in New Issue
Block a user