// // DataControllerHelper.swift // Reflect // // SwiftData helper and test data operations. // import SwiftData import Foundation extension DataController { func randomEntries(count: Int) -> [MoodEntryModel] { var entries = [MoodEntryModel]() for idx in 0.. MoodEntryModel { let entry = MoodEntryModel( forDate: date, moodValue: mood.rawValue, entryType: EntryType.listView.rawValue, canEdit: false, canDelete: false ) return entry } func populateTestData() { clearDB() for idx in 1..<1000 { let date = Calendar.current.date(byAdding: .day, value: -idx, to: Date())! let mood = Self.randomMood() let entry = MoodEntryModel( forDate: date, mood: mood, entryType: .listView, notes: Self.randomNotes(), weatherJSON: Self.randomWeatherJSON(for: date), reflectionJSON: Self.randomReflectionJSON(for: mood, on: date) ) modelContext.insert(entry) } saveAndRunDataListeners() } func populate2YearsData() { clearDB() for idx in 1...730 { let date = Calendar.current.date(byAdding: .day, value: -idx, to: Date())! let mood = Self.randomMood() let entry = MoodEntryModel( forDate: date, mood: mood, entryType: .listView, notes: Self.randomNotes(), weatherJSON: Self.randomWeatherJSON(for: date), reflectionJSON: Self.randomReflectionJSON(for: mood, on: date) ) modelContext.insert(entry) } saveAndRunDataListeners() } private static func randomMood() -> Mood { var moodValue = Int.random(in: 3...4) if Int.random(in: 0...400) % 5 == 0 { moodValue = Int.random(in: 0...4) } return Mood(rawValue: moodValue) ?? .average } // ~40% of entries get notes private static func randomNotes() -> String? { guard Bool.random() && Bool.random() == false else { return nil } return sampleNotes.randomElement() } private static let sampleNotes: [String] = [ "Had a productive morning and got a lot done.", "Went for a long walk in the park today.", "Feeling grateful for the little things.", "Tough meeting at work but pushed through.", "Spent quality time with family this evening.", "Couldn't sleep well last night, feeling tired.", "Great workout at the gym today!", "Read a really interesting book chapter.", "Cooked a new recipe and it turned out great.", "Feeling a bit anxious about tomorrow.", "Had coffee with an old friend, felt wonderful.", "Rainy day but cozy inside with a good movie.", "Got some bad news, trying to stay positive.", "Meditation session helped clear my mind.", "Busy day but managed to stay focused.", "Enjoyed a quiet evening at home.", "Felt overwhelmed by my to-do list.", "Beautiful sunset on the drive home.", "Tried journaling for the first time in a while.", "Had a really meaningful conversation today.", ] // ~25% of entries get guided reflections private static func randomReflectionJSON(for mood: Mood, on date: Date) -> String? { guard Int.random(in: 0...3) == 0 else { return nil } let category = MoodCategory(from: mood) let questions = GuidedReflection.questions(for: category) let answers = sampleAnswers(for: category) let responses = questions.enumerated().map { index, question in GuidedReflection.Response( id: index, question: question, answer: answers[index % answers.count] ) } let reflection = GuidedReflection( moodCategory: category, responses: responses, completedAt: date ) return reflection.encode() } private static func sampleAnswers(for category: MoodCategory) -> [String] { switch category { case .positive: return [ "I felt a sense of calm and contentment throughout the day.", "Connecting with a friend really lifted my spirits.", "I want to keep making time for the things that bring me joy.", ] case .neutral: return [ "A mix of emotions today, nothing too strong in either direction.", "Work was steady but unremarkable.", "I'd like to be more intentional about how I spend my evenings.", "Maybe adding a short walk after lunch could help.", ] case .negative: return [ "I've been worrying about things outside my control.", "A stressful interaction this morning set the tone for the day.", "I think I need some quiet time to recharge.", "Taking a few deep breaths and stepping away from screens.", ] } } private static let weatherConditions: [(symbol: String, condition: String)] = [ ("sun.max.fill", "Clear"), ("cloud.sun.fill", "Partly Cloudy"), ("cloud.fill", "Cloudy"), ("cloud.rain.fill", "Rain"), ("cloud.heavyrain.fill", "Heavy Rain"), ("cloud.drizzle.fill", "Drizzle"), ("cloud.bolt.fill", "Thunderstorms"), ("cloud.snow.fill", "Snow"), ("cloud.fog.fill", "Foggy"), ("wind", "Windy"), ("sun.haze.fill", "Hazy"), ] private static func randomWeatherJSON(for date: Date) -> String? { let condition = weatherConditions.randomElement()! let high = Double.random(in: 5...35) let low = high - Double.random(in: 5...15) let weather = WeatherData( conditionSymbol: condition.symbol, condition: condition.condition, temperature: (high + low) / 2.0, highTemperature: high, lowTemperature: low, humidity: Double.random(in: 0.2...0.95), latitude: 37.7749, longitude: -122.4194, fetchedAt: date ) return weather.encode() } func longestStreak() -> [MoodEntryModel] { let descriptor = FetchDescriptor( sortBy: [SortDescriptor(\.forDate, order: .forward)] ) return (try? modelContext.fetch(descriptor)) ?? [] } }