TargetPicker+Helper.swift 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import CoreData
  2. import Foundation
  3. import SwiftUI
  4. struct TargetPicker: View {
  5. let label: String
  6. @Binding var selection: Decimal
  7. let options: [Decimal]
  8. let units: GlucoseUnits
  9. @Binding var hasChanges: Bool
  10. @Binding var targetStep: Decimal
  11. @Binding var displayPickerTarget: Bool
  12. var toggleScrollWheel: (_ picker: Bool) -> Bool
  13. var body: some View {
  14. VStack {
  15. HStack {
  16. Text(label)
  17. Spacer()
  18. Text(
  19. (units == .mgdL ? selection.description : selection.formattedAsMmolL) + " " + units.rawValue
  20. )
  21. .foregroundColor(!displayPickerTarget ? .primary : .accentColor)
  22. }
  23. .onTapGesture {
  24. displayPickerTarget = toggleScrollWheel(displayPickerTarget)
  25. }
  26. if displayPickerTarget {
  27. HStack {
  28. // Radio buttons and text on the left side
  29. VStack(alignment: .leading) {
  30. // Radio buttons for step iteration
  31. let stepChoices: [Decimal] = units == .mgdL ? [1, 5] : [1, 9]
  32. ForEach(stepChoices, id: \.self) { step in
  33. let label = (units == .mgdL ? step.description : step.formattedAsMmolL) + " " +
  34. units.rawValue
  35. RadioButton(
  36. isSelected: targetStep == step,
  37. label: label
  38. ) {
  39. targetStep = step
  40. selection = OverrideConfig.StateModel.roundTargetToStep(selection, step)
  41. }
  42. .padding(.top, 10)
  43. }
  44. }
  45. .frame(maxWidth: .infinity)
  46. Spacer()
  47. // Picker on the right side
  48. Picker(selection: Binding(
  49. get: { OverrideConfig.StateModel.roundTargetToStep(selection, targetStep) },
  50. set: {
  51. selection = $0
  52. hasChanges = true
  53. }
  54. ), label: Text("")) {
  55. ForEach(options, id: \.self) { option in
  56. Text((units == .mgdL ? option.description : option.formattedAsMmolL) + " " + units.rawValue)
  57. .tag(option)
  58. }
  59. }
  60. .pickerStyle(WheelPickerStyle())
  61. .frame(maxWidth: .infinity)
  62. }
  63. .listRowSeparator(.hidden, edges: .top)
  64. }
  65. }
  66. }
  67. }
  68. enum TargetHelper {
  69. func computeHalfBasalTarget(
  70. usingTarget initialTarget: Decimal? = nil,
  71. usingPercentage initialPercentage: Double? = nil
  72. ) -> Double {
  73. let adjustmentPercentage = initialPercentage ?? percentage
  74. let adjustmentRatio = Decimal(adjustmentPercentage / 100)
  75. let tempTargetValue: Decimal = initialTarget ?? tempTargetTarget
  76. var halfBasalTargetValue = halfBasalTarget
  77. if adjustmentRatio != 1 {
  78. halfBasalTargetValue = ((2 * adjustmentRatio * normalTarget) - normalTarget - (adjustmentRatio * tempTargetValue)) /
  79. (adjustmentRatio - 1)
  80. }
  81. return round(Double(halfBasalTargetValue))
  82. }
  83. func computeSliderLow(usingTarget initialTarget: Decimal? = nil) -> Double {
  84. let calcTarget = initialTarget ?? tempTargetTarget
  85. guard calcTarget != 0 else { return 15 }
  86. let shouldRaiseSensitivity = settingsManager.preferences.highTemptargetRaisesSensitivity
  87. let isExerciseModeActive = settingsManager.preferences.exerciseMode
  88. let isTargetNormalOrLower = calcTarget <= normalTarget
  89. let minSens = (isTargetNormalOrLower || (!shouldRaiseSensitivity && !isExerciseModeActive)) ? 100 : 15
  90. return Double(max(0, minSens))
  91. }
  92. func computeSliderHigh(usingTarget initialTarget: Decimal? = nil) -> Double {
  93. let calcTarget = initialTarget ?? tempTargetTarget
  94. guard calcTarget != 0 else { return Double(maxValue * 100) }
  95. let shouldLowerSensitivity = settingsManager.preferences.lowTemptargetLowersSensitivity
  96. let isTargetNormalOrHigher = calcTarget >= normalTarget
  97. let maxSens = (isTargetNormalOrHigher || !shouldLowerSensitivity) ? 100 : Double(maxValue * 100)
  98. return maxSens
  99. }
  100. func computeAdjustedPercentage(
  101. usingHBT initialHalfBasalTarget: Decimal? = nil,
  102. usingTarget initialTarget: Decimal? = nil
  103. ) -> Decimal {
  104. let halfBasalTargetValue = initialHalfBasalTarget ?? halfBasalTarget
  105. let calcTarget = initialTarget ?? tempTargetTarget
  106. let deviationFromNormal = halfBasalTargetValue - normalTarget
  107. let adjustmentFactor = deviationFromNormal + (calcTarget - normalTarget)
  108. let adjustmentRatio: Decimal = (deviationFromNormal * adjustmentFactor <= 0) ? maxValue : deviationFromNormal /
  109. adjustmentFactor
  110. return min(adjustmentRatio, maxValue)
  111. }
  112. }