| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- import CoreData
- import Foundation
- extension Home.StateModel {
- // Asynchronously preprocess Forecast data in a background thread
- func preprocessForecastData() async -> [(
- id: UUID, forecastID: NSManagedObjectID, forecastValueIDs: [NSManagedObjectID]
- )] {
- do {
- // Get the Determination ID on the main context
- guard let determination = await viewContext.perform({
- self.enactedAndNonEnactedDeterminations.first
- }) else {
- debug(.default, "No determination found for forecast preprocessing")
- return []
- }
- // Fetch complete forecast hierarchy with prefetched values
- return try await determinationStorage.fetchForecastHierarchy(
- for: determination.objectID,
- in: taskContext
- )
- } catch {
- debug(
- .default,
- "\(DebuggingIdentifiers.failed) Failed to preprocess forecast data: \(error.localizedDescription)"
- )
- return []
- }
- }
- // Update forecast data and UI on the main thread
- @MainActor func updateForecastData() async {
- let forecastDataIDs = await preprocessForecastData()
- var allForecastValues = [[Int]]()
- var preprocessedData = [(id: UUID, forecast: Forecast, forecastValue: ForecastValue)]()
- // Process prefetched data directly
- for data in forecastDataIDs {
- if let forecast = try? viewContext.existingObject(with: data.forecastID) as? Forecast {
- let values = data.forecastValueIDs.compactMap {
- try? viewContext.existingObject(with: $0) as? ForecastValue
- }
- // Extract values for graph
- let forecastValueInts = values.map { Int($0.value) }
- allForecastValues.append(forecastValueInts)
- // Add data for further processing
- preprocessedData.append(contentsOf: values.map {
- (id: data.id, forecast: forecast, forecastValue: $0)
- })
- }
- }
- // Update UI-relevant data
- self.preprocessedData = preprocessedData
- guard !allForecastValues.isEmpty else {
- minForecast = []
- maxForecast = []
- return
- }
- minCount = max(12, allForecastValues.map(\.count).min() ?? 0)
- let localMinCount = minCount
- guard localMinCount > 0 else { return }
- // Calculate min/max values for graph
- let (minResult, maxResult) = await Task.detached {
- let minForecast = (0 ..< localMinCount).map { index in
- allForecastValues.compactMap { $0.indices.contains(index) ? $0[index] : nil }
- .min() ?? 0
- }
- let maxForecast = (0 ..< localMinCount).map { index in
- allForecastValues.compactMap { $0.indices.contains(index) ? $0[index] : nil }
- .max() ?? 0
- }
- return (minForecast, maxForecast)
- }.value
- minForecast = minResult
- maxForecast = maxResult
- }
- }
|