From 94d19abb6ba60280393e2938e9704b6ea22c0f9d Mon Sep 17 00:00:00 2001 From: kristinkand Date: Thu, 1 Oct 2026 15:44:04 +0200 Subject: [PATCH 1/3] Add Time in Range band to home screen --- .../MainViewController+updateStats.swift | 36 ++++++++ .../Controllers/StatsDisplayModel.swift | 8 ++ LoopFollow/Controllers/TIRBandView.swift | 85 +++++++++++++++++++ LoopFollow/Settings/GeneralSettingsView.swift | 7 ++ LoopFollow/Settings/SettingsMenuView.swift | 2 + .../Settings/UnitsConfigurationView.swift | 16 ++++ LoopFollow/Storage/Storage.swift | 2 + LoopFollow/ViewControllers/MainHomeView.swift | 7 +- 8 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 LoopFollow/Controllers/TIRBandView.swift diff --git a/LoopFollow/Controllers/MainViewController+updateStats.swift b/LoopFollow/Controllers/MainViewController+updateStats.swift index f3c4c0d10..45c500512 100644 --- a/LoopFollow/Controllers/MainViewController+updateStats.swift +++ b/LoopFollow/Controllers/MainViewController+updateStats.swift @@ -48,5 +48,41 @@ extension MainViewController { statsDisplayModel.pieRange = Double(stats.percentRange) statsDisplayModel.pieHigh = Double(stats.percentHigh) } + updateTIRBand() + } + + /// Today's (since midnight) range distribution for the Time in Range band. + /// Very low is below 54 mg/dL; low, in range and high follow the Range Mode + /// chosen in Settings (TIR, TITR or Custom). + func updateTIRBand() { + let thresholds = UnitSettingsStore.shared.effectiveThresholds() + let startOfDay = Calendar.current.startOfDay(for: Date()).timeIntervalSince1970 + let values = bgData + .filter { $0.date >= startOfDay && $0.sgv > 0 } + .map { Double($0.sgv) } + + switch UnitSettingsStore.shared.timeInRangeMode { + case .tir: statsDisplayModel.bandTitle = "Time in Range" + case .titr: statsDisplayModel.bandTitle = "Time in Tight Range" + case .custom: statsDisplayModel.bandTitle = "Time in Range" + } + + guard !values.isEmpty else { + statsDisplayModel.bandHasData = false + statsDisplayModel.bandVeryLowPct = 0 + statsDisplayModel.bandLowPct = 0 + statsDisplayModel.bandInRangePct = 0 + statsDisplayModel.bandHighPct = 0 + return + } + + let total = Double(values.count) + func pct(_ count: Int) -> Double { Double(count) / total * 100 } + + statsDisplayModel.bandVeryLowPct = pct(values.filter { $0 < 54 }.count) + statsDisplayModel.bandLowPct = pct(values.filter { $0 >= 54 && $0 < thresholds.low }.count) + statsDisplayModel.bandInRangePct = pct(values.filter { $0 >= thresholds.low && $0 <= thresholds.high }.count) + statsDisplayModel.bandHighPct = pct(values.filter { $0 > thresholds.high }.count) + statsDisplayModel.bandHasData = true } } diff --git a/LoopFollow/Controllers/StatsDisplayModel.swift b/LoopFollow/Controllers/StatsDisplayModel.swift index 72e60560a..a120c8812 100644 --- a/LoopFollow/Controllers/StatsDisplayModel.swift +++ b/LoopFollow/Controllers/StatsDisplayModel.swift @@ -15,4 +15,12 @@ class StatsDisplayModel: ObservableObject { @Published var pieLow: Double = 0 @Published var pieRange: Double = 0 @Published var pieHigh: Double = 0 + + // Time in Range band (today since midnight) + @Published var bandTitle: String = "Time in Range" + @Published var bandHasData: Bool = false + @Published var bandVeryLowPct: Double = 0 + @Published var bandLowPct: Double = 0 + @Published var bandInRangePct: Double = 0 + @Published var bandHighPct: Double = 0 } diff --git a/LoopFollow/Controllers/TIRBandView.swift b/LoopFollow/Controllers/TIRBandView.swift new file mode 100644 index 000000000..04e29a06a --- /dev/null +++ b/LoopFollow/Controllers/TIRBandView.swift @@ -0,0 +1,85 @@ +// LoopFollow +// TIRBandView.swift + +import SwiftUI + +/// Time in Range band for the home screen: today's in-range +/// percentage above a segmented bar (very low / low / in range / high). +/// The range follows the Range Mode in Settings (TIR, TITR or Custom). +/// Tapping opens the statistics screen. +struct TIRBandView: View { + @ObservedObject var model: StatsDisplayModel + var onTap: (() -> Void)? + + private var percentText: String { + guard model.bandHasData else { return "-- %" } + return model.bandInRangePct.formatted(.number.precision(.fractionLength(0 ... 1))) + " %" + } + + private var segments: [(color: Color, fraction: CGFloat)] { + guard model.bandHasData else { return [(Color.secondary.opacity(0.3), 1)] } + return [ + (.red, CGFloat(model.bandVeryLowPct / 100)), + (.orange, CGFloat(model.bandLowPct / 100)), + (.green, CGFloat(model.bandInRangePct / 100)), + (.purple, CGFloat(model.bandHighPct / 100)), + ] + } + + var body: some View { + HStack(alignment: .center, spacing: 12) { + VStack(alignment: .leading, spacing: 6) { + HStack(alignment: .firstTextBaseline, spacing: 6) { + Text(percentText) + .font(.title2) + .fontWeight(.bold) + .fontDesign(.rounded) + .foregroundStyle(.primary) + (Text(model.bandTitle).fontWeight(.semibold) + Text(" today")) + .font(.subheadline) + .foregroundStyle(.secondary) + .lineLimit(1) + .minimumScaleFactor(0.8) + } + + DistributionBar(segments: segments) + .frame(height: 6) + } + + Spacer(minLength: 8) + + Image(systemName: "chevron.right") + .font(.system(size: 15, weight: .semibold)) + .foregroundStyle(.secondary) + } + .padding(.horizontal, 16) + .frame(height: 64) + .background( + RoundedRectangle(cornerRadius: 14, style: .continuous) + .fill(Color(.secondarySystemBackground)) + ) + .contentShape(Rectangle()) + .onTapGesture { onTap?() } + } +} + +/// Horizontal bar of capsules, one per non-empty segment, sized by share. +private struct DistributionBar: View { + let segments: [(color: Color, fraction: CGFloat)] + + var body: some View { + GeometryReader { geo in + let spacing: CGFloat = 2 + let shown = segments.filter { $0.fraction > 0.005 } + let available = max(geo.size.width - spacing * CGFloat(max(shown.count - 1, 0)), 0) + HStack(spacing: spacing) { + ForEach(Array(shown.enumerated()), id: \.offset) { _, segment in + Capsule() + .fill(segment.color) + .frame(width: available * segment.fraction) + } + } + .frame(maxHeight: .infinity) + } + } +} diff --git a/LoopFollow/Settings/GeneralSettingsView.swift b/LoopFollow/Settings/GeneralSettingsView.swift index 0ac3acc69..75608ae57 100644 --- a/LoopFollow/Settings/GeneralSettingsView.swift +++ b/LoopFollow/Settings/GeneralSettingsView.swift @@ -8,6 +8,7 @@ struct GeneralSettingsView: View { @ObservedObject var appBadge = Storage.shared.appBadge @ObservedObject var appearanceMode = Storage.shared.appearanceMode @ObservedObject var showStats = Storage.shared.showStats + @ObservedObject var showTIRBand = Storage.shared.showTIRBand @ObservedObject var showSmallGraph = Storage.shared.showSmallGraph @ObservedObject var screenlockSwitchState = Storage.shared.screenlockSwitchState @ObservedObject var showDisplayName = Storage.shared.showDisplayName @@ -45,6 +46,12 @@ struct GeneralSettingsView: View { } } Toggle("Display Stats", isOn: $showStats.value) + if showStats.value { + Picker("Stats Style", selection: $showTIRBand.value) { + Text("Statistics Box").tag(false) + Text("Time in Range Band").tag(true) + } + } Toggle("Display Small Graph", isOn: $showSmallGraph.value) Toggle("Color BG Text", isOn: $colorBGText.value) Toggle("Keep Screen Active", isOn: $screenlockSwitchState.value) diff --git a/LoopFollow/Settings/SettingsMenuView.swift b/LoopFollow/Settings/SettingsMenuView.swift index 93fd0fd93..5ace5adf5 100644 --- a/LoopFollow/Settings/SettingsMenuView.swift +++ b/LoopFollow/Settings/SettingsMenuView.swift @@ -158,6 +158,7 @@ enum SettingsRoute: Hashable, Identifiable { SettingsLeaf("Persistent Notification"), SettingsLeaf("Appearance", ["dark mode", "light mode", "theme"]), SettingsLeaf("Display Stats"), + SettingsLeaf("Stats Style", ["time in range band", "statistics box", "tir band", "progress bar"]), SettingsLeaf("Display Small Graph"), SettingsLeaf("Color BG Text"), SettingsLeaf("Keep Screen Active", ["screen lock", "screenlock"]), @@ -192,6 +193,7 @@ enum SettingsRoute: Hashable, Identifiable { + InfoType.allCases.map { SettingsLeaf($0.name) } case .units: return [ SettingsLeaf("Glucose Unit"), + SettingsLeaf("Home Screen Stats", ["stats style", "time in range band", "statistics box", "progress bar"]), SettingsLeaf("Range Mode", ["tir", "titr", "time in range"]), SettingsLeaf("Glycemic Metrics", ["hba1c", "ehba1c", "gmi"]), SettingsLeaf("Variability", ["standard deviation", "cv"]), diff --git a/LoopFollow/Settings/UnitsConfigurationView.swift b/LoopFollow/Settings/UnitsConfigurationView.swift index 2124077c7..311805eb6 100644 --- a/LoopFollow/Settings/UnitsConfigurationView.swift +++ b/LoopFollow/Settings/UnitsConfigurationView.swift @@ -25,6 +25,8 @@ struct UnitsConfigurationView: View { var sections: Sections = .all @State private var rangeMode = UnitSettingsStore.shared.timeInRangeMode + @ObservedObject private var showStats = Storage.shared.showStats + @ObservedObject private var showTIRBand = Storage.shared.showTIRBand @State private var glucoseUnit = UnitSettingsStore.shared.glucoseUnit @State private var lowValue = Storage.shared.lowLine.value @State private var highValue = Storage.shared.highLine.value @@ -67,6 +69,20 @@ struct UnitsConfigurationView: View { @ViewBuilder private var statisticsSections: some View { Group { + Section { + Toggle("Display Stats", isOn: $showStats.value) + if showStats.value { + Picker("Stats Style", selection: $showTIRBand.value) { + Text("Statistics Box").tag(false) + Text("Time in Range Band").tag(true) + } + } + } header: { + Text("Home Screen Stats") + } footer: { + Text("Statistics Box shows the pie chart, averages and A1C for the last 24 hours. Time in Range Band shows today's time in range for the Range Mode below. The same setting is in General.") + } + Section { Picker("Range Mode", selection: $rangeMode) { Text("TIR").tag(TimeInRangeDisplayMode.tir) diff --git a/LoopFollow/Storage/Storage.swift b/LoopFollow/Storage/Storage.swift index dd63f6dd6..5e8f254f8 100644 --- a/LoopFollow/Storage/Storage.swift +++ b/LoopFollow/Storage/Storage.swift @@ -70,6 +70,8 @@ class Storage { var colorBGText = StorageValue(key: "colorBGText", defaultValue: true) var appearanceMode = StorageValue(key: "appearanceMode", defaultValue: .dark) var showStats = StorageValue(key: "showStats", defaultValue: true) + /// Show the home screen stats as a Time in Range band instead of the statistics box. + var showTIRBand = StorageValue(key: "showTIRBand", defaultValue: false) var useIFCC = StorageValue(key: "useIFCC", defaultValue: false) var showSmallGraph = StorageValue(key: "showSmallGraph", defaultValue: true) var screenlockSwitchState = StorageValue(key: "screenlockSwitchState", defaultValue: true) diff --git a/LoopFollow/ViewControllers/MainHomeView.swift b/LoopFollow/ViewControllers/MainHomeView.swift index 599120f7d..5be5c0a2f 100644 --- a/LoopFollow/ViewControllers/MainHomeView.swift +++ b/LoopFollow/ViewControllers/MainHomeView.swift @@ -13,6 +13,7 @@ struct MainHomeView: View { @ObservedObject var showSmallGraph = Storage.shared.showSmallGraph @ObservedObject var showStats = Storage.shared.showStats + @ObservedObject var showTIRBand = Storage.shared.showTIRBand @ObservedObject var hideInfoTable = Storage.shared.hideInfoTable @ObservedObject var smallGraphHeight = Storage.shared.smallGraphHeight @ObservedObject var url = Storage.shared.url @@ -64,7 +65,11 @@ struct MainHomeView: View { // Statistics if showStats.value { - StatsDisplayView(model: statsModel, onTap: onStatsTap) + if showTIRBand.value { + TIRBandView(model: statsModel, onTap: onStatsTap) + } else { + StatsDisplayView(model: statsModel, onTap: onStatsTap) + } } } .padding(8) From e2ffc3bee3204ab5cb8923fbd49c4e81508a949f Mon Sep 17 00:00:00 2001 From: kristinkand Date: Thu, 1 Oct 2026 15:45:43 +0200 Subject: [PATCH 2/3] Refresh home screen stats when Range Mode changes --- LoopFollow/ViewControllers/MainViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/LoopFollow/ViewControllers/MainViewController.swift b/LoopFollow/ViewControllers/MainViewController.swift index 06c5e1f76..507119d1c 100644 --- a/LoopFollow/ViewControllers/MainViewController.swift +++ b/LoopFollow/ViewControllers/MainViewController.swift @@ -282,6 +282,7 @@ class MainViewController: UIViewController, UNUserNotificationCenterDelegate { .sink { [weak self] _ in self?.updateBGGraphSettings() self?.updateBGGraph() + self?.updateStats() } .store(in: &cancellables) From 28dc97eb0824b9117e45b18b5c52f80ae6ab1247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B6rkert?= Date: Sat, 10 Oct 2026 13:37:27 +0200 Subject: [PATCH 3/3] Fix TIR band counting and match the stats screen The band now uses TIRCalculator, so each reading is counted once with the same 54 and 250 mg/dL cutoffs as the TIR chart in Stats. It also has a very high segment and uses the same colors as that chart. Every non-empty segment gets a minimum width so a single low reading stays visible, and the bar fills the full width of the band. The Stats Style setting is only in General. --- .../MainViewController+updateStats.swift | 33 ++++++++--------- .../Controllers/StatsDisplayModel.swift | 1 + LoopFollow/Controllers/TIRBandView.swift | 36 +++++++++++++------ LoopFollow/Settings/SettingsMenuView.swift | 1 - .../Settings/UnitsConfigurationView.swift | 16 --------- LoopFollow/Stats/TIR/TIRCalculator.swift | 10 +++--- LoopFollow/Stats/TIR/TIRGraphView.swift | 2 +- 7 files changed, 47 insertions(+), 52 deletions(-) diff --git a/LoopFollow/Controllers/MainViewController+updateStats.swift b/LoopFollow/Controllers/MainViewController+updateStats.swift index 45c500512..582f325eb 100644 --- a/LoopFollow/Controllers/MainViewController+updateStats.swift +++ b/LoopFollow/Controllers/MainViewController+updateStats.swift @@ -52,8 +52,8 @@ extension MainViewController { } /// Today's (since midnight) range distribution for the Time in Range band. - /// Very low is below 54 mg/dL; low, in range and high follow the Range Mode - /// chosen in Settings (TIR, TITR or Custom). + /// Very low is below 54 mg/dL and very high above 250 mg/dL; low, in range + /// and high follow the Range Mode chosen in Settings (TIR, TITR or Custom). func updateTIRBand() { let thresholds = UnitSettingsStore.shared.effectiveThresholds() let startOfDay = Calendar.current.startOfDay(for: Date()).timeIntervalSince1970 @@ -67,22 +67,19 @@ extension MainViewController { case .custom: statsDisplayModel.bandTitle = "Time in Range" } - guard !values.isEmpty else { - statsDisplayModel.bandHasData = false - statsDisplayModel.bandVeryLowPct = 0 - statsDisplayModel.bandLowPct = 0 - statsDisplayModel.bandInRangePct = 0 - statsDisplayModel.bandHighPct = 0 - return - } - - let total = Double(values.count) - func pct(_ count: Int) -> Double { Double(count) / total * 100 } + let percentages = TIRCalculator.calculatePercentages( + readings: values, + veryLowThreshold: 54.0, + lowThreshold: thresholds.low, + highThreshold: thresholds.high, + veryHighThreshold: 250.0 + ) - statsDisplayModel.bandVeryLowPct = pct(values.filter { $0 < 54 }.count) - statsDisplayModel.bandLowPct = pct(values.filter { $0 >= 54 && $0 < thresholds.low }.count) - statsDisplayModel.bandInRangePct = pct(values.filter { $0 >= thresholds.low && $0 <= thresholds.high }.count) - statsDisplayModel.bandHighPct = pct(values.filter { $0 > thresholds.high }.count) - statsDisplayModel.bandHasData = true + statsDisplayModel.bandVeryLowPct = percentages.veryLow + statsDisplayModel.bandLowPct = percentages.low + statsDisplayModel.bandInRangePct = percentages.inRange + statsDisplayModel.bandHighPct = percentages.high + statsDisplayModel.bandVeryHighPct = percentages.veryHigh + statsDisplayModel.bandHasData = !values.isEmpty } } diff --git a/LoopFollow/Controllers/StatsDisplayModel.swift b/LoopFollow/Controllers/StatsDisplayModel.swift index a120c8812..8f3f75d0b 100644 --- a/LoopFollow/Controllers/StatsDisplayModel.swift +++ b/LoopFollow/Controllers/StatsDisplayModel.swift @@ -23,4 +23,5 @@ class StatsDisplayModel: ObservableObject { @Published var bandLowPct: Double = 0 @Published var bandInRangePct: Double = 0 @Published var bandHighPct: Double = 0 + @Published var bandVeryHighPct: Double = 0 } diff --git a/LoopFollow/Controllers/TIRBandView.swift b/LoopFollow/Controllers/TIRBandView.swift index 04e29a06a..06fbe4ffc 100644 --- a/LoopFollow/Controllers/TIRBandView.swift +++ b/LoopFollow/Controllers/TIRBandView.swift @@ -4,7 +4,7 @@ import SwiftUI /// Time in Range band for the home screen: today's in-range -/// percentage above a segmented bar (very low / low / in range / high). +/// percentage above a segmented bar (very low / low / in range / high / very high). /// The range follows the Range Mode in Settings (TIR, TITR or Custom). /// Tapping opens the statistics screen. struct TIRBandView: View { @@ -19,10 +19,11 @@ struct TIRBandView: View { private var segments: [(color: Color, fraction: CGFloat)] { guard model.bandHasData else { return [(Color.secondary.opacity(0.3), 1)] } return [ - (.red, CGFloat(model.bandVeryLowPct / 100)), - (.orange, CGFloat(model.bandLowPct / 100)), - (.green, CGFloat(model.bandInRangePct / 100)), - (.purple, CGFloat(model.bandHighPct / 100)), + (TIRGraphView.Band.veryLow.color, CGFloat(model.bandVeryLowPct / 100)), + (TIRGraphView.Band.low.color, CGFloat(model.bandLowPct / 100)), + (TIRGraphView.Band.inRange.color, CGFloat(model.bandInRangePct / 100)), + (TIRGraphView.Band.high.color, CGFloat(model.bandHighPct / 100)), + (TIRGraphView.Band.veryHigh.color, CGFloat(model.bandVeryHighPct / 100)), ] } @@ -45,8 +46,7 @@ struct TIRBandView: View { DistributionBar(segments: segments) .frame(height: 6) } - - Spacer(minLength: 8) + .frame(maxWidth: .infinity, alignment: .leading) Image(systemName: "chevron.right") .font(.system(size: 15, weight: .semibold)) @@ -64,22 +64,36 @@ struct TIRBandView: View { } /// Horizontal bar of capsules, one per non-empty segment, sized by share. +/// Every non-empty segment is at least `minSegmentWidth` wide so a single +/// reading stays visible. private struct DistributionBar: View { let segments: [(color: Color, fraction: CGFloat)] + private let spacing: CGFloat = 2 + private let minSegmentWidth: CGFloat = 4 + var body: some View { GeometryReader { geo in - let spacing: CGFloat = 2 - let shown = segments.filter { $0.fraction > 0.005 } + let shown = segments.filter { $0.fraction > 0 } let available = max(geo.size.width - spacing * CGFloat(max(shown.count - 1, 0)), 0) + let widths = segmentWidths(shown.map(\.fraction), available: available) HStack(spacing: spacing) { - ForEach(Array(shown.enumerated()), id: \.offset) { _, segment in + ForEach(Array(shown.enumerated()), id: \.offset) { index, segment in Capsule() .fill(segment.color) - .frame(width: available * segment.fraction) + .frame(width: widths[index]) } } .frame(maxHeight: .infinity) } } + + private func segmentWidths(_ fractions: [CGFloat], available: CGFloat) -> [CGFloat] { + var widths = fractions.map { max($0 * available, minSegmentWidth) } + let excess = widths.reduce(0, +) - available + if excess > 0, let widest = widths.indices.max(by: { widths[$0] < widths[$1] }) { + widths[widest] = max(widths[widest] - excess, minSegmentWidth) + } + return widths + } } diff --git a/LoopFollow/Settings/SettingsMenuView.swift b/LoopFollow/Settings/SettingsMenuView.swift index 5ace5adf5..7c0a875dd 100644 --- a/LoopFollow/Settings/SettingsMenuView.swift +++ b/LoopFollow/Settings/SettingsMenuView.swift @@ -193,7 +193,6 @@ enum SettingsRoute: Hashable, Identifiable { + InfoType.allCases.map { SettingsLeaf($0.name) } case .units: return [ SettingsLeaf("Glucose Unit"), - SettingsLeaf("Home Screen Stats", ["stats style", "time in range band", "statistics box", "progress bar"]), SettingsLeaf("Range Mode", ["tir", "titr", "time in range"]), SettingsLeaf("Glycemic Metrics", ["hba1c", "ehba1c", "gmi"]), SettingsLeaf("Variability", ["standard deviation", "cv"]), diff --git a/LoopFollow/Settings/UnitsConfigurationView.swift b/LoopFollow/Settings/UnitsConfigurationView.swift index 311805eb6..2124077c7 100644 --- a/LoopFollow/Settings/UnitsConfigurationView.swift +++ b/LoopFollow/Settings/UnitsConfigurationView.swift @@ -25,8 +25,6 @@ struct UnitsConfigurationView: View { var sections: Sections = .all @State private var rangeMode = UnitSettingsStore.shared.timeInRangeMode - @ObservedObject private var showStats = Storage.shared.showStats - @ObservedObject private var showTIRBand = Storage.shared.showTIRBand @State private var glucoseUnit = UnitSettingsStore.shared.glucoseUnit @State private var lowValue = Storage.shared.lowLine.value @State private var highValue = Storage.shared.highLine.value @@ -69,20 +67,6 @@ struct UnitsConfigurationView: View { @ViewBuilder private var statisticsSections: some View { Group { - Section { - Toggle("Display Stats", isOn: $showStats.value) - if showStats.value { - Picker("Stats Style", selection: $showTIRBand.value) { - Text("Statistics Box").tag(false) - Text("Time in Range Band").tag(true) - } - } - } header: { - Text("Home Screen Stats") - } footer: { - Text("Statistics Box shows the pie chart, averages and A1C for the last 24 hours. Time in Range Band shows today's time in range for the Range Mode below. The same setting is in General.") - } - Section { Picker("Range Mode", selection: $rangeMode) { Text("TIR").tag(TimeInRangeDisplayMode.tir) diff --git a/LoopFollow/Stats/TIR/TIRCalculator.swift b/LoopFollow/Stats/TIR/TIRCalculator.swift index b387b5702..af814a5dd 100644 --- a/LoopFollow/Stats/TIR/TIRCalculator.swift +++ b/LoopFollow/Stats/TIR/TIRCalculator.swift @@ -91,11 +91,11 @@ class TIRCalculator { return tirPoints } - private static func calculatePercentages(readings: [Double], - veryLowThreshold: Double, - lowThreshold: Double, - highThreshold: Double, - veryHighThreshold: Double) -> (veryLow: Double, low: Double, inRange: Double, high: Double, veryHigh: Double) + static func calculatePercentages(readings: [Double], + veryLowThreshold: Double, + lowThreshold: Double, + highThreshold: Double, + veryHighThreshold: Double) -> (veryLow: Double, low: Double, inRange: Double, high: Double, veryHigh: Double) { let total = Double(readings.count) guard total > 0 else { diff --git a/LoopFollow/Stats/TIR/TIRGraphView.swift b/LoopFollow/Stats/TIR/TIRGraphView.swift index 03a84a14b..1eba0f767 100644 --- a/LoopFollow/Stats/TIR/TIRGraphView.swift +++ b/LoopFollow/Stats/TIR/TIRGraphView.swift @@ -7,7 +7,7 @@ import SwiftUI struct TIRGraphView: View { let tirData: [TIRDataPoint] - private enum Band: String, CaseIterable, Plottable { + enum Band: String, CaseIterable, Plottable { case veryLow = "Very Low" case low = "Low" case inRange = "In Range"