Просмотр исходного кода

Merge pull request #161 from dsnallfot/refactored-mmol-reasonstring-parsing

Refactor Determination Reason String (rT.reason) mmol/L Parsing
Deniz Cengiz 1 год назад
Родитель
Сommit
19e1c07cc0

+ 79 - 28
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -1046,38 +1046,89 @@ extension Home {
             }
         }
 
-        private func parseReasonConclusion(_ reasonConclusion: String, isMmolL: Bool) -> String {
-            var updatedConclusion = reasonConclusion
-
-            // Handle "minGuardBG x<y" pattern
-            if let range = updatedConclusion.range(of: "minGuardBG\\s*-?\\d+<\\d+", options: .regularExpression) {
-                let matchedString = updatedConclusion[range]
-                let parts = matchedString.components(separatedBy: "<")
-
-                if let firstValue = Double(parts[0].components(separatedBy: CharacterSet.decimalDigits.inverted).joined()),
-                   let secondValue = Double(parts[1])
-                {
-                    let formattedFirstValue = isMmolL ? Double(firstValue.asMmolL) : firstValue
-                    let formattedSecondValue = isMmolL ? Double(secondValue.asMmolL) : secondValue
-
-                    let formattedString = "minGuardBG \(formattedFirstValue)<\(formattedSecondValue)"
-                    updatedConclusion = updatedConclusion.replacingOccurrences(of: matchedString, with: formattedString)
+        //TODO: Consolidate all mmol parsing methods (in TagCloudView, NightscoutManager and HomeRootView) to one central func
+        private func parseReasonConclusion(_ reasonConclusion: String, isMmolL _: Bool) -> String {
+            let patterns = [
+                "minGuardBG\\s*-?\\d+\\.?\\d*<-?\\d+\\.?\\d*",
+                "Eventual BG\\s*-?\\d+\\.?\\d*\\s*>=\\s*-?\\d+\\.?\\d*",
+                "\\S+\\s+-?\\d+\\.?\\d*\\s*>\\s*\\d+%\\s+of\\s+BG\\s+-?\\d+\\.?\\d*"
+            ]
+            let pattern = patterns.joined(separator: "|")
+            let regex = try! NSRegularExpression(pattern: pattern)
+
+            func convertToMmolL(_ value: String) -> String {
+                if let glucoseValue = Double(value.replacingOccurrences(of: "[^\\d.-]", with: "", options: .regularExpression)) {
+                    let mmolValue = Decimal(glucoseValue).asMmolL
+                    return mmolValue.description
                 }
+                return value
             }
 
-            // Handle "Eventual BG x >= target" pattern
-            if let range = updatedConclusion.range(of: "Eventual BG\\s*\\d+\\s*>?=\\s*\\d+", options: .regularExpression) {
-                let matchedString = updatedConclusion[range]
-                let parts = matchedString.components(separatedBy: " >= ")
-
-                if let firstValue = Double(parts[0].components(separatedBy: CharacterSet.decimalDigits.inverted).joined()),
-                   let secondValue = Double(parts[1])
-                {
-                    let formattedFirstValue = isMmolL ? Double(firstValue.asMmolL) : firstValue
-                    let formattedSecondValue = isMmolL ? Double(secondValue.asMmolL) : secondValue
+            let matches = regex.matches(
+                in: reasonConclusion,
+                range: NSRange(reasonConclusion.startIndex..., in: reasonConclusion)
+            )
+            var updatedConclusion = reasonConclusion
 
-                    let formattedString = "Eventual BG \(formattedFirstValue) >= \(formattedSecondValue)"
-                    updatedConclusion = updatedConclusion.replacingOccurrences(of: matchedString, with: formattedString)
+            for match in matches.reversed() {
+                guard let range = Range(match.range, in: reasonConclusion) else { continue }
+                let matchedString = String(reasonConclusion[range])
+
+                if matchedString.contains("<") {
+                    // Handle "minGuardBG x<y" pattern
+                    let parts = matchedString.components(separatedBy: "<")
+                    if parts.count == 2,
+                       let firstValue = Double(
+                           parts[0]
+                               .components(separatedBy: CharacterSet(charactersIn: "0123456789.-").inverted).joined()
+                       ),
+                       let secondValue = Double(
+                           parts[1]
+                               .components(separatedBy: CharacterSet(charactersIn: "0123456789.-").inverted).joined()
+                       )
+                    {
+                        let formattedFirstValue = convertToMmolL(String(firstValue))
+                        let formattedSecondValue = convertToMmolL(String(secondValue))
+                        let formattedString = "minGuardBG \(formattedFirstValue)<\(formattedSecondValue)"
+                        updatedConclusion.replaceSubrange(range, with: formattedString)
+                    }
+                } else if matchedString.contains(">=") {
+                    // Handle "Eventual BG x >= target" pattern
+                    let parts = matchedString.components(separatedBy: " >= ")
+                    if parts.count == 2,
+                       let firstValue = Double(
+                           parts[0]
+                               .components(separatedBy: CharacterSet(charactersIn: "0123456789.-").inverted).joined()
+                       ),
+                       let secondValue = Double(
+                           parts[1]
+                               .components(separatedBy: CharacterSet(charactersIn: "0123456789.-").inverted).joined()
+                       )
+                    {
+                        let formattedFirstValue = convertToMmolL(String(firstValue))
+                        let formattedSecondValue = convertToMmolL(String(secondValue))
+                        let formattedString = "Eventual BG \(formattedFirstValue) >= \(formattedSecondValue)"
+                        updatedConclusion.replaceSubrange(range, with: formattedString)
+                    }
+                } else if matchedString.contains(">") {
+                    // Handle "maxDelta 37 > 20% of BG 95" style
+                    let pattern = "(\\S+)\\s+(-?\\d+\\.?\\d*)\\s*>\\s*(\\d+)%\\s+of\\s+BG\\s+(-?\\d+\\.?\\d*)"
+                    let localRegex = try! NSRegularExpression(pattern: pattern)
+                    if let localMatch = localRegex.firstMatch(
+                        in: matchedString,
+                        range: NSRange(matchedString.startIndex..., in: matchedString)
+                    ) {
+                        let metric = String(matchedString[Range(localMatch.range(at: 1), in: matchedString)!])
+                        let firstValue = String(matchedString[Range(localMatch.range(at: 2), in: matchedString)!])
+                        let percentage = String(matchedString[Range(localMatch.range(at: 3), in: matchedString)!])
+                        let bgValue = String(matchedString[Range(localMatch.range(at: 4), in: matchedString)!])
+
+                        let formattedFirstValue = convertToMmolL(firstValue)
+                        let formattedBGValue = convertToMmolL(bgValue)
+
+                        let formattedString = "\(metric) \(formattedFirstValue) > \(percentage)% of BG \(formattedBGValue)"
+                        updatedConclusion.replaceSubrange(range, with: formattedString)
+                    }
                 }
             }
 

+ 113 - 47
FreeAPS/Sources/Services/Network/Nightscout/NightscoutManager.swift

@@ -1149,18 +1149,28 @@ extension BaseNightscoutManager {
      - Returns:
        A string with glucose values converted to mmol/L.
 
-     - Glucose tags handled: `ISF:`, `Target:`, `minPredBG`, `minGuardBG`, `IOBpredBG`, `COBpredBG`, `UAMpredBG`, `Dev:`, `maxDelta`, `BG`.
+     - Glucose tags handled: `ISF:`, `Target:`, `minPredBG`, `minGuardBG`, `IOBpredBG`, `COBpredBG`, `UAMpredBG`, `Dev:`, `maxDelta`, `BGI`.
      */
-    func parseReasonGlucoseValuesToMmolL(_ reason: String) -> String {
-        // Updated pattern to handle cases like minGuardBG 34, minGuardBG 34<70, and "maxDelta 37 > 20% of BG 95", and ensure "Target:" is handled correctly
-        let pattern =
-            "(ISF:\\s*-?\\d+→-?\\d+|Dev:\\s*-?\\d+|Target:\\s*-?\\d+|(?:minPredBG|minGuardBG|IOBpredBG|COBpredBG|UAMpredBG|maxDelta|BG)\\s*-?\\d+(?:<\\d+)?(?:>\\s*\\d+%\\s*of\\s*BG\\s*\\d+)?)"
 
+     //TODO: Consolidate all mmol parsing methods (in TagCloudView, NightscoutManager and HomeRootView) to one central func
+    func parseReasonGlucoseValuesToMmolL(_ reason: String) -> String {
+        let patterns = [
+            "ISF:\\s*-?\\d+\\.?\\d*→-?\\d+\\.?\\d*",
+            "Dev:\\s*-?\\d+\\.?\\d*",
+            "BGI:\\s*-?\\d+\\.?\\d*",
+            "Target:\\s*-?\\d+\\.?\\d*",
+            "(?:minPredBG|minGuardBG|IOBpredBG|COBpredBG|UAMpredBG)\\s+-?\\d+\\.?\\d*(?:<-?\\d+\\.?\\d*)?",
+            "minGuardBG\\s+-?\\d+\\.?\\d*<-?\\d+\\.?\\d*",
+            "Eventual BG\\s+-?\\d+\\.?\\d*\\s*>=\\s*-?\\d+\\.?\\d*",
+            "\\S+\\s+\\d+\\s*>\\s*\\d+%\\s+of\\s+BG\\s+\\d+"
+        ]
+        let pattern = patterns.joined(separator: "|")
         let regex = try! NSRegularExpression(pattern: pattern)
 
         func convertToMmolL(_ value: String) -> String {
             if let glucoseValue = Double(value.replacingOccurrences(of: "[^\\d.-]", with: "", options: .regularExpression)) {
-                return glucoseValue.asMmolL.description
+                let mmolValue = Decimal(glucoseValue).asMmolL
+                return mmolValue.description
             }
             return value
         }
@@ -1169,47 +1179,103 @@ extension BaseNightscoutManager {
         var updatedReason = reason
 
         for match in matches.reversed() {
-            if let range = Range(match.range, in: reason) {
-                let glucoseValueString = String(reason[range])
-
-                if glucoseValueString.contains("→") {
-                    // Handle ISF case with an arrow (e.g., ISF: 54→54)
-                    let values = glucoseValueString.components(separatedBy: "→")
-                    let firstValue = convertToMmolL(values[0])
-                    let secondValue = convertToMmolL(values[1])
-                    let formattedGlucoseValueString = "\(values[0].components(separatedBy: ":")[0]): \(firstValue)→\(secondValue)"
-                    updatedReason.replaceSubrange(range, with: formattedGlucoseValueString)
-                } else if glucoseValueString.contains("<") {
-                    // Handle range case for minGuardBG like "minGuardBG 34<70"
-                    let values = glucoseValueString.components(separatedBy: "<")
-                    let firstValue = convertToMmolL(values[0])
-                    let secondValue = convertToMmolL(values[1])
-                    let formattedGlucoseValueString = "\(values[0].components(separatedBy: ":")[0]) \(firstValue)<\(secondValue)"
-                    updatedReason.replaceSubrange(range, with: formattedGlucoseValueString)
-                } else if glucoseValueString.contains(">"), glucoseValueString.contains("BG") {
-                    // Handle cases like "maxDelta 37 > 20% of BG 95"
-                    let pattern = "(\\d+) > \\d+% of BG (\\d+)"
-                    let matches = try! NSRegularExpression(pattern: pattern)
-                        .matches(in: glucoseValueString, range: NSRange(glucoseValueString.startIndex..., in: glucoseValueString))
-
-                    if let match = matches.first, match.numberOfRanges == 3 {
-                        let firstValueRange = Range(match.range(at: 1), in: glucoseValueString)!
-                        let secondValueRange = Range(match.range(at: 2), in: glucoseValueString)!
-
-                        let firstValue = convertToMmolL(String(glucoseValueString[firstValueRange]))
-                        let secondValue = convertToMmolL(String(glucoseValueString[secondValueRange]))
-
-                        let formattedGlucoseValueString = glucoseValueString.replacingOccurrences(
-                            of: "\(glucoseValueString[firstValueRange]) > 20% of BG \(glucoseValueString[secondValueRange])",
-                            with: "\(firstValue) > 20% of BG \(secondValue)"
-                        )
-                        updatedReason.replaceSubrange(range, with: formattedGlucoseValueString)
-                    }
-                } else {
-                    // General case for single glucose values like "Target: 100" or "minGuardBG 34"
-                    let parts = glucoseValueString.components(separatedBy: CharacterSet(charactersIn: ": "))
-                    let formattedValue = convertToMmolL(parts.last!.trimmingCharacters(in: .whitespaces))
-                    updatedReason.replaceSubrange(range, with: "\(parts[0]): \(formattedValue)")
+            guard let range = Range(match.range, in: reason) else { continue }
+            let glucoseValueString = String(reason[range])
+
+            if glucoseValueString.contains("→") {
+                // -- Handle ISF: X→Y
+                let values = glucoseValueString.components(separatedBy: "→")
+                let firstNumber = values[0].components(separatedBy: ":")[1].trimmingCharacters(in: .whitespaces)
+                let secondNumber = values[1].trimmingCharacters(in: .whitespaces)
+                let firstValue = convertToMmolL(firstNumber)
+                let secondValue = convertToMmolL(secondNumber)
+                let formattedString = "ISF: \(firstValue)→\(secondValue)"
+                updatedReason.replaceSubrange(range, with: formattedString)
+
+            } else if glucoseValueString.contains("<") {
+                // -- Handle minGuardBG (or minPredBG, etc.) x < y
+                let components = glucoseValueString
+                    .split(whereSeparator: { "<".contains($0) ||
+                            CharacterSet.whitespaces.contains($0.unicodeScalars.first!) })
+                    .filter { !$0.isEmpty }
+
+                if components.count >= 3 {
+                    let firstValue = convertToMmolL(String(components[1]))
+                    let secondValue = convertToMmolL(String(components[2]))
+                    let formattedString = "\(components[0]) \(firstValue)<\(secondValue)"
+                    updatedReason.replaceSubrange(range, with: formattedString)
+                }
+
+            } else if glucoseValueString.contains(">=") {
+                // -- Handle "Eventual BG X >= Y"
+                let components = glucoseValueString
+                    .split(whereSeparator: { " >= ".contains($0) ||
+                            CharacterSet.whitespaces.contains($0.unicodeScalars.first!) })
+                    .filter { !$0.isEmpty }
+
+                if components.count == 4 {
+                    let firstValue = convertToMmolL(String(components[2]))
+                    let secondValue = convertToMmolL(String(components[3]))
+                    let formattedString = "\(components[0]) \(components[1]) \(firstValue) >= \(secondValue)"
+                    updatedReason.replaceSubrange(range, with: formattedString)
+                }
+
+            } else if glucoseValueString.starts(with: "Dev:") {
+                // -- Handle Dev
+                let value = glucoseValueString.components(separatedBy: ":")[1].trimmingCharacters(in: .whitespaces)
+                let formattedValue = convertToMmolL(value)
+                let formattedString = "Dev: \(formattedValue)"
+                updatedReason.replaceSubrange(range, with: formattedString)
+
+            } else if glucoseValueString.starts(with: "BGI:") {
+                // -- Handle BGI
+                let value = glucoseValueString.components(separatedBy: ":")[1].trimmingCharacters(in: .whitespaces)
+                let formattedValue = convertToMmolL(value)
+                let formattedString = "BGI: \(formattedValue)"
+                updatedReason.replaceSubrange(range, with: formattedString)
+
+            } else if glucoseValueString.starts(with: "Target:") {
+                // -- Handle Target
+                let value = glucoseValueString.components(separatedBy: ":")[1].trimmingCharacters(in: .whitespaces)
+                let formattedValue = convertToMmolL(value)
+                let formattedString = "Target: \(formattedValue)"
+                updatedReason.replaceSubrange(range, with: formattedString)
+
+            } else if glucoseValueString.contains(">"), glucoseValueString.contains("BG") {
+                // -- Handle "maxDelta 37 > 20% of BG 95" style
+                // Run a local regex that picks out the two BG values
+                let localPattern = "(\\d+) > (\\d+)% of BG (\\d+)"
+                let localRegex = try! NSRegularExpression(pattern: localPattern)
+                let localMatches = localRegex.matches(
+                    in: glucoseValueString,
+                    range: NSRange(glucoseValueString.startIndex..., in: glucoseValueString)
+                )
+                if let localMatch = localMatches.first, localMatch.numberOfRanges == 4 {
+                    let range1 = Range(localMatch.range(at: 1), in: glucoseValueString)!
+                    let range2 = Range(localMatch.range(at: 2), in: glucoseValueString)!
+                    let range3 = Range(localMatch.range(at: 3), in: glucoseValueString)!
+
+                    let firstValue = convertToMmolL(String(glucoseValueString[range1]))
+                    let thirdValue = convertToMmolL(String(glucoseValueString[range3]))
+
+                    // e.g. "37 > 20% of BG 95" → "2.1 > 20% of BG 5.3"
+                    let oldSnippet =
+                        "\(glucoseValueString[range1]) > \(glucoseValueString[range2])% of BG \(glucoseValueString[range3])"
+                    let newSnippet = "\(firstValue) > \(glucoseValueString[range2])% of BG \(thirdValue)"
+
+                    let replaced = glucoseValueString.replacingOccurrences(of: oldSnippet, with: newSnippet)
+                    updatedReason.replaceSubrange(range, with: replaced)
+                }
+
+            } else {
+                // -- Handle everything else, e.g. "minPredBG 39" etc.
+                let parts = glucoseValueString.components(separatedBy: .whitespaces)
+                if parts.count >= 2 {
+                    let metric = parts[0]
+                    let value = parts[1]
+                    let formattedValue = convertToMmolL(value)
+                    let formattedString = "\(metric): \(formattedValue)"
+                    updatedReason.replaceSubrange(range, with: formattedString)
                 }
             }
         }

+ 59 - 47
FreeAPS/Sources/Views/TagCloudView.swift

@@ -101,18 +101,26 @@ struct TagCloudView: View {
      - Returns:
        A string with glucose values converted to mmol/L.
 
-     - Glucose tags handled: `ISF:`, `Target:`, `minPredBG`, `minGuardBG`, `IOBpredBG`, `COBpredBG`, `UAMpredBG`, `Dev:`, `maxDelta`, `BG`.
+     - Glucose tags handled: `ISF:`, `Target:`, `minPredBG`, `minGuardBG`, `IOBpredBG`, `COBpredBG`, `UAMpredBG`, `Dev:`, `maxDelta`, `BGI`.
      */
-    private func formatGlucoseTags(_ tag: String, isMmolL: Bool) -> String {
-        // Updated pattern to handle cases like minGuardBG 34, minGuardBG 34<70, "maxDelta 37 > 20% of BG 95", and ensure "Target:" is handled correctly
-        let pattern =
-            "(ISF:\\s*-?\\d+→-?\\d+|Dev:\\s*-?\\d+|Target:\\s*-?\\d+|(?:minPredBG|minGuardBG|IOBpredBG|COBpredBG|UAMpredBG|maxDelta|BG)\\s*-?\\d+(?:<\\d+)?(?:>\\s*\\d+%\\s*of\\s*BG\\s*\\d+)?)"
 
+     //TODO: Consolidate all mmol parsing methods (in TagCloudView, NightscoutManager and HomeRootView) to one central func
+    private func formatGlucoseTags(_ tag: String, isMmolL: Bool) -> String {
+        let patterns = [
+            "ISF:\\s*-?\\d+\\.?\\d*→-?\\d+\\.?\\d*",
+            "Dev:\\s*-?\\d+\\.?\\d*",
+            "BGI:\\s*-?\\d+\\.?\\d*",
+            "Target:\\s*-?\\d+\\.?\\d*",
+            "(?:minPredBG|minGuardBG|IOBpredBG|COBpredBG|UAMpredBG)\\s*-?\\d+\\.?\\d*"
+        ]
+        let pattern = patterns.joined(separator: "|")
         let regex = try! NSRegularExpression(pattern: pattern)
 
+        // Convert only if isMmolL == true; otherwise return original mg/dL string
         func convertToMmolL(_ value: String) -> String {
             if let glucoseValue = Double(value.replacingOccurrences(of: "[^\\d.-]", with: "", options: .regularExpression)) {
-                return isMmolL ? glucoseValue.asMmolL.description : value
+                let mmolValue = Decimal(glucoseValue).asMmolL // your mg/dL → mmol/L routine
+                return isMmolL ? mmolValue.description : value
             }
             return value
         }
@@ -120,48 +128,52 @@ struct TagCloudView: View {
         let matches = regex.matches(in: tag, range: NSRange(tag.startIndex..., in: tag))
         var updatedTag = tag
 
+        // Process each match in reverse order
         for match in matches.reversed() {
-            if let range = Range(match.range, in: tag) {
-                let glucoseValueString = String(tag[range])
-
-                if glucoseValueString.contains("→") {
-                    // Handle ISF case with an arrow (e.g., ISF: 54→54)
-                    let values = glucoseValueString.components(separatedBy: "→")
-                    let firstValue = convertToMmolL(values[0])
-                    let secondValue = convertToMmolL(values[1])
-                    let formattedGlucoseValueString = "\(values[0].components(separatedBy: ":")[0]): \(firstValue)→\(secondValue)"
-                    updatedTag.replaceSubrange(range, with: formattedGlucoseValueString)
-                } else if glucoseValueString.contains("<") {
-                    // Handle range case for minGuardBG like "minGuardBG 34<70"
-                    let values = glucoseValueString.components(separatedBy: "<")
-                    let firstValue = convertToMmolL(values[0])
-                    let secondValue = convertToMmolL(values[1])
-                    let formattedGlucoseValueString = "\(values[0].components(separatedBy: ":")[0]) \(firstValue)<\(secondValue)"
-                    updatedTag.replaceSubrange(range, with: formattedGlucoseValueString)
-                } else if glucoseValueString.contains(">"), glucoseValueString.contains("BG") {
-                    // Handle cases like "maxDelta 37 > 20% of BG 95"
-                    let pattern = "(\\d+) > \\d+% of BG (\\d+)"
-                    let matches = try! NSRegularExpression(pattern: pattern)
-                        .matches(in: glucoseValueString, range: NSRange(glucoseValueString.startIndex..., in: glucoseValueString))
-
-                    if let match = matches.first, match.numberOfRanges == 3 {
-                        let firstValueRange = Range(match.range(at: 1), in: glucoseValueString)!
-                        let secondValueRange = Range(match.range(at: 2), in: glucoseValueString)!
-
-                        let firstValue = convertToMmolL(String(glucoseValueString[firstValueRange]))
-                        let secondValue = convertToMmolL(String(glucoseValueString[secondValueRange]))
-
-                        let formattedGlucoseValueString = glucoseValueString.replacingOccurrences(
-                            of: "\(glucoseValueString[firstValueRange]) > 20% of BG \(glucoseValueString[secondValueRange])",
-                            with: "\(firstValue) > 20% of BG \(secondValue)"
-                        )
-                        updatedTag.replaceSubrange(range, with: formattedGlucoseValueString)
-                    }
-                } else {
-                    // General case for single glucose values like "Target: 100" or "minGuardBG 34"
-                    let parts = glucoseValueString.components(separatedBy: CharacterSet(charactersIn: ": "))
-                    let formattedValue = convertToMmolL(parts.last!.trimmingCharacters(in: .whitespaces))
-                    updatedTag.replaceSubrange(range, with: "\(parts[0]): \(formattedValue)")
+            guard let range = Range(match.range, in: tag) else { continue }
+            let glucoseValueString = String(tag[range])
+
+            if glucoseValueString.contains("→") {
+                // -- Handle ISF: X→Y
+                let values = glucoseValueString.components(separatedBy: "→")
+                // For example "ISF: 162"
+                let firstNumber = values[0].components(separatedBy: ":")[1].trimmingCharacters(in: .whitespaces)
+                let secondNumber = values[1].trimmingCharacters(in: .whitespaces)
+                let firstValue = convertToMmolL(firstNumber)
+                let secondValue = convertToMmolL(secondNumber)
+                let formattedString = "ISF: \(firstValue)→\(secondValue)"
+                updatedTag.replaceSubrange(range, with: formattedString)
+
+            } else if glucoseValueString.starts(with: "Dev:") {
+                // -- Handle Dev
+                let value = glucoseValueString.components(separatedBy: ":")[1].trimmingCharacters(in: .whitespaces)
+                let formattedValue = convertToMmolL(value)
+                let formattedString = "Dev: \(formattedValue)"
+                updatedTag.replaceSubrange(range, with: formattedString)
+
+            } else if glucoseValueString.starts(with: "BGI:") {
+                // -- Handle BGI
+                let value = glucoseValueString.components(separatedBy: ":")[1].trimmingCharacters(in: .whitespaces)
+                let formattedValue = convertToMmolL(value)
+                let formattedString = "BGI: \(formattedValue)"
+                updatedTag.replaceSubrange(range, with: formattedString)
+
+            } else if glucoseValueString.starts(with: "Target:") {
+                // -- Handle Target
+                let value = glucoseValueString.components(separatedBy: ":")[1].trimmingCharacters(in: .whitespaces)
+                let formattedValue = convertToMmolL(value)
+                let formattedString = "Target: \(formattedValue)"
+                updatedTag.replaceSubrange(range, with: formattedString)
+
+            } else {
+                // -- Handle everything else (e.g., "minPredBG 39" etc.)
+                let parts = glucoseValueString.components(separatedBy: .whitespaces)
+                if parts.count >= 2 {
+                    let metric = parts[0]
+                    let value = parts[1]
+                    let formattedValue = convertToMmolL(value)
+                    let formattedString = "\(metric): \(formattedValue)"
+                    updatedTag.replaceSubrange(range, with: formattedString)
                 }
             }
         }