import Chartsimport CodexBarCoreimport SwiftUI @MainActorstruct PlanUtilizationHistoryChartMenuView: View { private enum Layout { static let chartHeight: CGFloat = 130 static let detailHeight: CGFloat = 16 static let emptyStateHeight: CGFloat = chartHeight + detailHeight static let maxPoints = 30 static let maxAxisLabels = 4 static let barWidth: CGFloat = 6 } private struct SeriesSelection: Hashable { let name: PlanUtilizationSeriesName let windowMinutes: Int var id: String { "\(self.name.rawValue):\(self.windowMinutes)" } } private struct VisibleSeries: Identifiable, Equatable { let selection: SeriesSelection let title: String let history: PlanUtilizationSeriesHistory var id: String { self.selection.id } } private struct EntryPointAccumulator { let effectiveBoundaryDate: Date let displayBoundaryDate: Date let observedAt: Date let usedPercent: Double let hasObservedResetBoundary: Bool } private struct ResetBoundaryLattice { let referenceBoundaryDate: Date let windowInterval: TimeInterval } private struct Point: Identifiable { let id: Date let index: Int let date: Date let usedPercent: Double let isObserved: Bool } private struct Model { let points: [Point] let axisIndexes: [Double] let xDomain: ClosedRange<Double>? let pointsByID: [Date: Point] let pointsByIndex: [Int: Point] let barColor: Color let trackColor: Color } private let provider: UsageProvider private let histories: [PlanUtilizationSeriesHistory] private let snapshot: UsageSnapshot? private let width: CGFloat @State private var selectedSeriesID: String? @State private var selectedPointID: Date? init( provider: UsageProvider, histories: [PlanUtilizationSeriesHistory], snapshot: UsageSnapshot? = nil, width: CGFloat) { self.provider = provider self.histories = histories self.snapshot = snapshot self.width = width } var body: some View { let visibleSeries = Self.visibleSeries( histories: self.histories, provider: self.provider, snapshot: self.snapshot) let effectiveSelectedSeries = visibleSeries.first(where: { $0.id == self.selectedSeriesID }) ?? visibleSeries .first let model = Self.makeModel( history: effectiveSelectedSeries?.history, provider: self.provider, referenceDate: Date()) VStack(alignment: .leading, spacing: 10) { if visibleSeries.count > 1 { Picker(selection: Binding( get: { effectiveSelectedSeries?.id ?? "" }, set: { newValue in self.selectedSeriesID = newValue self.selectedPointID = nil })) { ForEach(visibleSeries) { series in Text(series.title).tag(series.id) } } label: { EmptyView() } .labelsHidden() .pickerStyle(.segmented) } if model.points.isEmpty { ZStack { Text(Self.emptyStateText(title: effectiveSelectedSeries?.title)) .font(.footnote) .foregroundStyle(.secondary) } .frame(maxWidth: .infinity) .frame(height: Layout.emptyStateHeight) } else { self.utilizationChart(model: model) .chartYAxis(.hidden) .chartYScale(domain: 0...100) .chartXAxis { AxisMarks(values: model.axisIndexes) { value in AxisGridLine().foregroundStyle(Color.clear) AxisTick().foregroundStyle(Color.clear) AxisValueLabel { if let raw = value.as(Double.self) { let index = Int(raw.rounded()) if let point = model.pointsByIndex[index] { let isTrailingFullChartLabel = index == model.points.last?.index && model.points.count == Layout.maxPoints Self.axisLabel( for: point, windowMinutes: effectiveSelectedSeries?.history.windowMinutes ?? 0, isTrailingFullChartLabel: isTrailingFullChartLabel) } } } } } .chartLegend(.hidden) .frame(height: Layout.chartHeight) .chartOverlay { proxy in GeometryReader { geo in MouseLocationReader { location in self.updateSelection(location: location, model: model, proxy: proxy, geo: geo) } .frame(maxWidth: .infinity, maxHeight: .infinity) .contentShape(Rectangle()) } } Text(self.detailLine(model: model, windowMinutes: effectiveSelectedSeries?.history.windowMinutes ?? 0)) .font(.caption) .foregroundStyle(.secondary) .lineLimit(1) .truncationMode(.tail) .frame(height: Layout.detailHeight, alignment: .leading) } } .padding(.horizontal, 16) .padding(.vertical, 10) .frame(minWidth: self.width, maxWidth: .infinity, alignment: .topLeading) .task(id: visibleSeries.map(\.id).joined(separator: ",")) { guard let firstVisibleSeries = visibleSeries.first else { return } guard !visibleSeries.contains(where: { $0.id == self.selectedSeriesID }) else { return } self.selectedSeriesID = firstVisibleSeries.id self.selectedPointID = nil } } private nonisolated static func visibleSeries( histories: [PlanUtilizationSeriesHistory], provider: UsageProvider, snapshot: UsageSnapshot?) -> [VisibleSeries] { let metadata = ProviderDescriptorRegistry.metadata[provider] let allowedNames = self.visibleSeriesNames(provider: provider, snapshot: snapshot) return histories .filter { history in guard !history.entries.isEmpty else { return false } guard let allowedNames else { return true } return allowedNames.contains(history.name) } .sorted { lhs, rhs in let lhsOrder = self.seriesSortOrder(lhs.name) let rhsOrder = self.seriesSortOrder(rhs.name) if lhsOrder != rhsOrder { return lhsOrder < rhsOrder } if lhs.windowMinutes != rhs.windowMinutes { return lhs.windowMinutes < rhs.windowMinutes } return lhs.name.rawValue < rhs.name.rawValue } .map { history in VisibleSeries( selection: SeriesSelection(name: history.name, windowMinutes: history.windowMinutes), title: self.seriesTitle(name: history.name, metadata: metadata), history: history) } } private nonisolated static func visibleSeriesNames( provider: UsageProvider, snapshot: UsageSnapshot?) -> Set<PlanUtilizationSeriesName>? { guard let snapshot else { return nil } var names: Set<PlanUtilizationSeriesName> = [] if snapshot.primary != nil { names.insert(.session) } if snapshot.secondary != nil { names.insert(.weekly) } if provider == .claude, snapshot.tertiary != nil, ProviderDescriptorRegistry.metadata[provider]?.supportsOpus == true { names.insert(.opus) } return names } private nonisolated static func makeModel( history: PlanUtilizationSeriesHistory?, provider: UsageProvider, referenceDate: Date) -> Model { guard let history else { return self.emptyModel(provider: provider) } var points = self.seriesPoints(history: history, referenceDate: referenceDate) if points.count > Layout.maxPoints { points = Array(points.suffix(Layout.maxPoints)) } points = points.enumerated().map { offset, point in Point( id: point.id, index: offset, date: point.date, usedPercent: point.usedPercent, isObserved: point.isObserved) } let pointsByID = Dictionary(uniqueKeysWithValues: points.map { ($0.id, $0) }) let pointsByIndex = Dictionary(uniqueKeysWithValues: points.map { ($0.index, $0) }) let color = ProviderDescriptorRegistry.descriptor(for: provider).branding.color let barColor = Color(red: color.red, green: color.green, blue: color.blue) let trackColor = MenuHighlightStyle.progressTrack(false) return Model( points: points, axisIndexes: self.axisIndexes(points: points, windowMinutes: history.windowMinutes), xDomain: self.xDomain(points: points), pointsByID: pointsByID, pointsByIndex: pointsByIndex, barColor: barColor, trackColor: trackColor) } private nonisolated static func emptyModel(provider: UsageProvider) -> Model { let color = ProviderDescriptorRegistry.descriptor(for: provider).branding.color let barColor = Color(red: color.red, green: color.green, blue: color.blue) let trackColor = MenuHighlightStyle.progressTrack(false) return Model( points: [], axisIndexes: [], xDomain: nil, pointsByID: [:], pointsByIndex: [:], barColor: barColor, trackColor: trackColor) } private nonisolated static func seriesPoints( history: PlanUtilizationSeriesHistory, referenceDate: Date) -> [Point] { guard history.windowMinutes > 0 else { return [] } let windowInterval = Double(history.windowMinutes) * 60 let resetBoundaryLattice = self.resetBoundaryLattice( entries: history.entries, windowMinutes: history.windowMinutes) var strongestObservedPointByPeriod: [Date: EntryPointAccumulator] = [:] for entry in history.entries { let candidate = self.observedPointCandidate( for: entry, windowMinutes: history.windowMinutes, resetBoundaryLattice: resetBoundaryLattice) if let existing = strongestObservedPointByPeriod[candidate.effectiveBoundaryDate], !self.shouldPreferObservedPoint(candidate, over: existing) { continue } strongestObservedPointByPeriod[candidate.effectiveBoundaryDate] = candidate } guard !strongestObservedPointByPeriod.isEmpty else { return [] } let sortedPeriodBoundaryDates = strongestObservedPointByPeriod.keys.sorted() var points: [Point] = [] var previousPeriodBoundaryDate: Date? for periodBoundaryDate in sortedPeriodBoundaryDates { if let previousPeriodBoundaryDate { var cursor = previousPeriodBoundaryDate.addingTimeInterval(windowInterval) while cursor < periodBoundaryDate { points.append(Point( id: cursor, index: 0, date: cursor, usedPercent: 0, isObserved: false)) cursor = cursor.addingTimeInterval(windowInterval) } } if let bucket = strongestObservedPointByPeriod[periodBoundaryDate] { points.append(Point( id: bucket.effectiveBoundaryDate, index: 0, date: bucket.displayBoundaryDate, usedPercent: bucket.usedPercent, isObserved: true)) } previousPeriodBoundaryDate = periodBoundaryDate } if let lastObservedPeriodBoundaryDate = sortedPeriodBoundaryDates.last { let currentPeriodBoundaryDate = self.currentPeriodBoundaryDate( for: referenceDate, windowMinutes: history.windowMinutes, resetBoundaryLattice: resetBoundaryLattice) if currentPeriodBoundaryDate > lastObservedPeriodBoundaryDate { var cursor = lastObservedPeriodBoundaryDate.addingTimeInterval(windowInterval) while cursor <= currentPeriodBoundaryDate { points.append(Point( id: cursor, index: 0, date: cursor, usedPercent: 0, isObserved: false)) cursor = cursor.addingTimeInterval(windowInterval) } } } return points } private nonisolated static func observedPointCandidate( for entry: PlanUtilizationHistoryEntry, windowMinutes: Int, resetBoundaryLattice: ResetBoundaryLattice?) -> EntryPointAccumulator { let rawResetBoundaryDate = entry.resetsAt.map(self.normalizedBoundaryDate) let effectiveBoundaryDate = self.effectivePeriodBoundaryDate( for: entry, windowMinutes: windowMinutes, rawResetBoundaryDate: rawResetBoundaryDate, resetBoundaryLattice: resetBoundaryLattice) return EntryPointAccumulator( effectiveBoundaryDate: effectiveBoundaryDate, displayBoundaryDate: rawResetBoundaryDate ?? effectiveBoundaryDate, observedAt: entry.capturedAt, usedPercent: max(0, min(100, entry.usedPercent)), hasObservedResetBoundary: rawResetBoundaryDate != nil) } private nonisolated static func resetBoundaryLattice( entries: [PlanUtilizationHistoryEntry], windowMinutes: Int) -> ResetBoundaryLattice? { guard let latestObservedResetBoundaryDate = entries .compactMap(\.resetsAt) .map(self.normalizedBoundaryDate) .max() else { return nil } return ResetBoundaryLattice( referenceBoundaryDate: latestObservedResetBoundaryDate, windowInterval: Double(windowMinutes) * 60) } private nonisolated static func normalizedBoundaryDate(_ date: Date) -> Date { Date(timeIntervalSince1970: floor(date.timeIntervalSince1970)) } private nonisolated static func effectivePeriodBoundaryDate( for entry: PlanUtilizationHistoryEntry, windowMinutes: Int, rawResetBoundaryDate: Date?, resetBoundaryLattice: ResetBoundaryLattice?) -> Date { if let rawResetBoundaryDate { if let resetBoundaryLattice { return self.closestPeriodBoundaryDate( to: rawResetBoundaryDate, resetBoundaryLattice: resetBoundaryLattice) } return rawResetBoundaryDate } if let resetBoundaryLattice { return self.periodBoundaryDate( containing: entry.capturedAt, resetBoundaryLattice: resetBoundaryLattice) } return self.syntheticBoundaryDate(for: entry.capturedAt, windowMinutes: windowMinutes) } private nonisolated static func shouldPreferObservedPoint( _ candidate: EntryPointAccumulator, over existing: EntryPointAccumulator) -> Bool { if candidate.usedPercent != existing.usedPercent { return candidate.usedPercent > existing.usedPercent } if candidate.hasObservedResetBoundary != existing.hasObservedResetBoundary { return candidate.hasObservedResetBoundary } if candidate.displayBoundaryDate != existing.displayBoundaryDate { return candidate.displayBoundaryDate > existing.displayBoundaryDate } return candidate.observedAt >= existing.observedAt } private nonisolated static func currentPeriodBoundaryDate( for referenceDate: Date, windowMinutes: Int, resetBoundaryLattice: ResetBoundaryLattice?) -> Date { if let resetBoundaryLattice { return self.periodBoundaryDate( containing: referenceDate, resetBoundaryLattice: resetBoundaryLattice) } return self.syntheticBoundaryDate(for: referenceDate, windowMinutes: windowMinutes) } private nonisolated static func closestPeriodBoundaryDate( to rawBoundaryDate: Date, resetBoundaryLattice: ResetBoundaryLattice) -> Date { let offset = rawBoundaryDate.timeIntervalSince(resetBoundaryLattice.referenceBoundaryDate) let periodOffset = (offset / resetBoundaryLattice.windowInterval).rounded() return resetBoundaryLattice.referenceBoundaryDate .addingTimeInterval(periodOffset * resetBoundaryLattice.windowInterval) } private nonisolated static func periodBoundaryDate( containing capturedAt: Date, resetBoundaryLattice: ResetBoundaryLattice) -> Date { let offset = capturedAt.timeIntervalSince(resetBoundaryLattice.referenceBoundaryDate) let periodOffset = ceil(offset / resetBoundaryLattice.windowInterval) return resetBoundaryLattice.referenceBoundaryDate .addingTimeInterval(periodOffset * resetBoundaryLattice.windowInterval) } private nonisolated static func syntheticBoundaryDate(for date: Date, windowMinutes: Int) -> Date { let bucketSeconds = Double(windowMinutes) * 60 let bucketIndex = floor(date.timeIntervalSince1970 / bucketSeconds) return Date(timeIntervalSince1970: (bucketIndex + 1) * bucketSeconds) } private nonisolated static func xDomain(points: [Point]) -> ClosedRange<Double>? { guard !points.isEmpty else { return nil } return -0.5...(Double(Layout.maxPoints) - 0.5) } private nonisolated static func axisIndexes(points: [Point], windowMinutes: Int) -> [Double] { let candidateIndexes = self.axisCandidateIndexes(points: points, windowMinutes: windowMinutes) return self.proportionalAxisIndexes(points: points, candidateIndexes: candidateIndexes) } private nonisolated static func axisCandidateIndexes(points: [Point], windowMinutes: Int) -> [Int] { if windowMinutes <= 300 { return self.sessionAxisCandidateIndexes(points: points) } return points.map(\.index) } private nonisolated static func sessionAxisCandidateIndexes(points: [Point]) -> [Int] { guard let firstPoint = points.first else { return [] }Lines 1–500 of 797. Load more
import Charts import CodexBarCore import SwiftUI @MainActor struct PlanUtilizationHistoryChartMenuView: View { private enum Layout { static let chartHeight: CGFloat = 130 static let detailHeight: CGFloat = 16 static let emptyStateHeight: CGFloat = chartHeight + detailHeight static let maxPoints = 30 static let maxAxisLabels = 4 static let barWidth: CGFloat = 6 } private struct SeriesSelection: Hashable { let name: PlanUtilizationSeriesName let windowMinutes: Int var id: String { "\(self.name.rawValue):\(self.windowMinutes)" } } private struct VisibleSeries: Identifiable, Equatable { let selection: SeriesSelection let title: String let history: PlanUtilizationSeriesHistory var id: String { self.selection.id } } private struct EntryPointAccumulator { let effectiveBoundaryDate: Date let displayBoundaryDate: Date let observedAt: Date let usedPercent: Double let hasObservedResetBoundary: Bool } private struct ResetBoundaryLattice { let referenceBoundaryDate: Date let windowInterval: TimeInterval } private struct Point: Identifiable { let id: Date let index: Int let date: Date let usedPercent: Double let isObserved: Bool } private struct Model { let points: [Point] let axisIndexes: [Double] let xDomain: ClosedRange<Double>? let pointsByID: [Date: Point] let pointsByIndex: [Int: Point] let barColor: Color let trackColor: Color } private let provider: UsageProvider private let histories: [PlanUtilizationSeriesHistory] private let snapshot: UsageSnapshot? private let width: CGFloat @State private var selectedSeriesID: String? @State private var selectedPointID: Date? init( provider: UsageProvider, histories: [PlanUtilizationSeriesHistory], snapshot: UsageSnapshot? = nil, width: CGFloat) { self.provider = provider self.histories = histories self.snapshot = snapshot self.width = width } var body: some View { let visibleSeries = Self.visibleSeries( histories: self.histories, provider: self.provider, snapshot: self.snapshot) let effectiveSelectedSeries = visibleSeries.first(where: { $0.id == self.selectedSeriesID }) ?? visibleSeries .first let model = Self.makeModel( history: effectiveSelectedSeries?.history, provider: self.provider, referenceDate: Date()) VStack(alignment: .leading, spacing: 10) { if visibleSeries.count > 1 { Picker(selection: Binding( get: { effectiveSelectedSeries?.id ?? "" }, set: { newValue in self.selectedSeriesID = newValue self.selectedPointID = nil })) { ForEach(visibleSeries) { series in Text(series.title).tag(series.id) } } label: { EmptyView() } .labelsHidden() .pickerStyle(.segmented) } if model.points.isEmpty { ZStack { Text(Self.emptyStateText(title: effectiveSelectedSeries?.title)) .font(.footnote) .foregroundStyle(.secondary) } .frame(maxWidth: .infinity) .frame(height: Layout.emptyStateHeight) } else { self.utilizationChart(model: model) .chartYAxis(.hidden) .chartYScale(domain: 0...100) .chartXAxis { AxisMarks(values: model.axisIndexes) { value in AxisGridLine().foregroundStyle(Color.clear) AxisTick().foregroundStyle(Color.clear) AxisValueLabel { if let raw = value.as(Double.self) { let index = Int(raw.rounded()) if let point = model.pointsByIndex[index] { let isTrailingFullChartLabel = index == model.points.last?.index && model.points.count == Layout.maxPoints Self.axisLabel( for: point, windowMinutes: effectiveSelectedSeries?.history.windowMinutes ?? 0, isTrailingFullChartLabel: isTrailingFullChartLabel) } } } } } .chartLegend(.hidden) .frame(height: Layout.chartHeight) .chartOverlay { proxy in GeometryReader { geo in MouseLocationReader { location in self.updateSelection(location: location, model: model, proxy: proxy, geo: geo) } .frame(maxWidth: .infinity, maxHeight: .infinity) .contentShape(Rectangle()) } } Text(self.detailLine(model: model, windowMinutes: effectiveSelectedSeries?.history.windowMinutes ?? 0)) .font(.caption) .foregroundStyle(.secondary) .lineLimit(1) .truncationMode(.tail) .frame(height: Layout.detailHeight, alignment: .leading) } } .padding(.horizontal, 16) .padding(.vertical, 10) .frame(minWidth: self.width, maxWidth: .infinity, alignment: .topLeading) .task(id: visibleSeries.map(\.id).joined(separator: ",")) { guard let firstVisibleSeries = visibleSeries.first else { return } guard !visibleSeries.contains(where: { $0.id == self.selectedSeriesID }) else { return } self.selectedSeriesID = firstVisibleSeries.id self.selectedPointID = nil } } private nonisolated static func visibleSeries( histories: [PlanUtilizationSeriesHistory], provider: UsageProvider, snapshot: UsageSnapshot?) -> [VisibleSeries] { let metadata = ProviderDescriptorRegistry.metadata[provider] let allowedNames = self.visibleSeriesNames(provider: provider, snapshot: snapshot) return histories .filter { history in guard !history.entries.isEmpty else { return false } guard let allowedNames else { return true } return allowedNames.contains(history.name) } .sorted { lhs, rhs in let lhsOrder = self.seriesSortOrder(lhs.name) let rhsOrder = self.seriesSortOrder(rhs.name) if lhsOrder != rhsOrder { return lhsOrder < rhsOrder } if lhs.windowMinutes != rhs.windowMinutes { return lhs.windowMinutes < rhs.windowMinutes } return lhs.name.rawValue < rhs.name.rawValue } .map { history in VisibleSeries( selection: SeriesSelection(name: history.name, windowMinutes: history.windowMinutes), title: self.seriesTitle(name: history.name, metadata: metadata), history: history) } } private nonisolated static func visibleSeriesNames( provider: UsageProvider, snapshot: UsageSnapshot?) -> Set<PlanUtilizationSeriesName>? { guard let snapshot else { return nil } var names: Set<PlanUtilizationSeriesName> = [] if snapshot.primary != nil { names.insert(.session) } if snapshot.secondary != nil { names.insert(.weekly) } if provider == .claude, snapshot.tertiary != nil, ProviderDescriptorRegistry.metadata[provider]?.supportsOpus == true { names.insert(.opus) } return names } private nonisolated static func makeModel( history: PlanUtilizationSeriesHistory?, provider: UsageProvider, referenceDate: Date) -> Model { guard let history else { return self.emptyModel(provider: provider) } var points = self.seriesPoints(history: history, referenceDate: referenceDate) if points.count > Layout.maxPoints { points = Array(points.suffix(Layout.maxPoints)) } points = points.enumerated().map { offset, point in Point( id: point.id, index: offset, date: point.date, usedPercent: point.usedPercent, isObserved: point.isObserved) } let pointsByID = Dictionary(uniqueKeysWithValues: points.map { ($0.id, $0) }) let pointsByIndex = Dictionary(uniqueKeysWithValues: points.map { ($0.index, $0) }) let color = ProviderDescriptorRegistry.descriptor(for: provider).branding.color let barColor = Color(red: color.red, green: color.green, blue: color.blue) let trackColor = MenuHighlightStyle.progressTrack(false) return Model( points: points, axisIndexes: self.axisIndexes(points: points, windowMinutes: history.windowMinutes), xDomain: self.xDomain(points: points), pointsByID: pointsByID, pointsByIndex: pointsByIndex, barColor: barColor, trackColor: trackColor) } private nonisolated static func emptyModel(provider: UsageProvider) -> Model { let color = ProviderDescriptorRegistry.descriptor(for: provider).branding.color let barColor = Color(red: color.red, green: color.green, blue: color.blue) let trackColor = MenuHighlightStyle.progressTrack(false) return Model( points: [], axisIndexes: [], xDomain: nil, pointsByID: [:], pointsByIndex: [:], barColor: barColor, trackColor: trackColor) } private nonisolated static func seriesPoints( history: PlanUtilizationSeriesHistory, referenceDate: Date) -> [Point] { guard history.windowMinutes > 0 else { return [] } let windowInterval = Double(history.windowMinutes) * 60 let resetBoundaryLattice = self.resetBoundaryLattice( entries: history.entries, windowMinutes: history.windowMinutes) var strongestObservedPointByPeriod: [Date: EntryPointAccumulator] = [:] for entry in history.entries { let candidate = self.observedPointCandidate( for: entry, windowMinutes: history.windowMinutes, resetBoundaryLattice: resetBoundaryLattice) if let existing = strongestObservedPointByPeriod[candidate.effectiveBoundaryDate], !self.shouldPreferObservedPoint(candidate, over: existing) { continue } strongestObservedPointByPeriod[candidate.effectiveBoundaryDate] = candidate } guard !strongestObservedPointByPeriod.isEmpty else { return [] } let sortedPeriodBoundaryDates = strongestObservedPointByPeriod.keys.sorted() var points: [Point] = [] var previousPeriodBoundaryDate: Date? for periodBoundaryDate in sortedPeriodBoundaryDates { if let previousPeriodBoundaryDate { var cursor = previousPeriodBoundaryDate.addingTimeInterval(windowInterval) while cursor < periodBoundaryDate { points.append(Point( id: cursor, index: 0, date: cursor, usedPercent: 0, isObserved: false)) cursor = cursor.addingTimeInterval(windowInterval) } } if let bucket = strongestObservedPointByPeriod[periodBoundaryDate] { points.append(Point( id: bucket.effectiveBoundaryDate, index: 0, date: bucket.displayBoundaryDate, usedPercent: bucket.usedPercent, isObserved: true)) } previousPeriodBoundaryDate = periodBoundaryDate } if let lastObservedPeriodBoundaryDate = sortedPeriodBoundaryDates.last { let currentPeriodBoundaryDate = self.currentPeriodBoundaryDate( for: referenceDate, windowMinutes: history.windowMinutes, resetBoundaryLattice: resetBoundaryLattice) if currentPeriodBoundaryDate > lastObservedPeriodBoundaryDate { var cursor = lastObservedPeriodBoundaryDate.addingTimeInterval(windowInterval) while cursor <= currentPeriodBoundaryDate { points.append(Point( id: cursor, index: 0, date: cursor, usedPercent: 0, isObserved: false)) cursor = cursor.addingTimeInterval(windowInterval) } } } return points } private nonisolated static func observedPointCandidate( for entry: PlanUtilizationHistoryEntry, windowMinutes: Int, resetBoundaryLattice: ResetBoundaryLattice?) -> EntryPointAccumulator { let rawResetBoundaryDate = entry.resetsAt.map(self.normalizedBoundaryDate) let effectiveBoundaryDate = self.effectivePeriodBoundaryDate( for: entry, windowMinutes: windowMinutes, rawResetBoundaryDate: rawResetBoundaryDate, resetBoundaryLattice: resetBoundaryLattice) return EntryPointAccumulator( effectiveBoundaryDate: effectiveBoundaryDate, displayBoundaryDate: rawResetBoundaryDate ?? effectiveBoundaryDate, observedAt: entry.capturedAt, usedPercent: max(0, min(100, entry.usedPercent)), hasObservedResetBoundary: rawResetBoundaryDate != nil) } private nonisolated static func resetBoundaryLattice( entries: [PlanUtilizationHistoryEntry], windowMinutes: Int) -> ResetBoundaryLattice? { guard let latestObservedResetBoundaryDate = entries .compactMap(\.resetsAt) .map(self.normalizedBoundaryDate) .max() else { return nil } return ResetBoundaryLattice( referenceBoundaryDate: latestObservedResetBoundaryDate, windowInterval: Double(windowMinutes) * 60) } private nonisolated static func normalizedBoundaryDate(_ date: Date) -> Date { Date(timeIntervalSince1970: floor(date.timeIntervalSince1970)) } private nonisolated static func effectivePeriodBoundaryDate( for entry: PlanUtilizationHistoryEntry, windowMinutes: Int, rawResetBoundaryDate: Date?, resetBoundaryLattice: ResetBoundaryLattice?) -> Date { if let rawResetBoundaryDate { if let resetBoundaryLattice { return self.closestPeriodBoundaryDate( to: rawResetBoundaryDate, resetBoundaryLattice: resetBoundaryLattice) } return rawResetBoundaryDate } if let resetBoundaryLattice { return self.periodBoundaryDate( containing: entry.capturedAt, resetBoundaryLattice: resetBoundaryLattice) } return self.syntheticBoundaryDate(for: entry.capturedAt, windowMinutes: windowMinutes) } private nonisolated static func shouldPreferObservedPoint( _ candidate: EntryPointAccumulator, over existing: EntryPointAccumulator) -> Bool { if candidate.usedPercent != existing.usedPercent { return candidate.usedPercent > existing.usedPercent } if candidate.hasObservedResetBoundary != existing.hasObservedResetBoundary { return candidate.hasObservedResetBoundary } if candidate.displayBoundaryDate != existing.displayBoundaryDate { return candidate.displayBoundaryDate > existing.displayBoundaryDate } return candidate.observedAt >= existing.observedAt } private nonisolated static func currentPeriodBoundaryDate( for referenceDate: Date, windowMinutes: Int, resetBoundaryLattice: ResetBoundaryLattice?) -> Date { if let resetBoundaryLattice { return self.periodBoundaryDate( containing: referenceDate, resetBoundaryLattice: resetBoundaryLattice) } return self.syntheticBoundaryDate(for: referenceDate, windowMinutes: windowMinutes) } private nonisolated static func closestPeriodBoundaryDate( to rawBoundaryDate: Date, resetBoundaryLattice: ResetBoundaryLattice) -> Date { let offset = rawBoundaryDate.timeIntervalSince(resetBoundaryLattice.referenceBoundaryDate) let periodOffset = (offset / resetBoundaryLattice.windowInterval).rounded() return resetBoundaryLattice.referenceBoundaryDate .addingTimeInterval(periodOffset * resetBoundaryLattice.windowInterval) } private nonisolated static func periodBoundaryDate( containing capturedAt: Date, resetBoundaryLattice: ResetBoundaryLattice) -> Date { let offset = capturedAt.timeIntervalSince(resetBoundaryLattice.referenceBoundaryDate) let periodOffset = ceil(offset / resetBoundaryLattice.windowInterval) return resetBoundaryLattice.referenceBoundaryDate .addingTimeInterval(periodOffset * resetBoundaryLattice.windowInterval) } private nonisolated static func syntheticBoundaryDate(for date: Date, windowMinutes: Int) -> Date { let bucketSeconds = Double(windowMinutes) * 60 let bucketIndex = floor(date.timeIntervalSince1970 / bucketSeconds) return Date(timeIntervalSince1970: (bucketIndex + 1) * bucketSeconds) } private nonisolated static func xDomain(points: [Point]) -> ClosedRange<Double>? { guard !points.isEmpty else { return nil } return -0.5...(Double(Layout.maxPoints) - 0.5) } private nonisolated static func axisIndexes(points: [Point], windowMinutes: Int) -> [Double] { let candidateIndexes = self.axisCandidateIndexes(points: points, windowMinutes: windowMinutes) return self.proportionalAxisIndexes(points: points, candidateIndexes: candidateIndexes) } private nonisolated static func axisCandidateIndexes(points: [Point], windowMinutes: Int) -> [Int] { if windowMinutes <= 300 { return self.sessionAxisCandidateIndexes(points: points) } return points.map(\.index) } private nonisolated static func sessionAxisCandidateIndexes(points: [Point]) -> [Int] { guard let firstPoint = points.first else { return [] }