소스 검색

Delete replay tests and code

Sam King 1 개월 전
부모
커밋
1644e6a988
37개의 변경된 파일17개의 추가작업 그리고 3548개의 파일을 삭제
  1. 4 177
      Trio.xcodeproj/project.pbxproj
  2. 0 202
      Trio/Sources/APS/OpenAPSSwift/Logging/AlgorithmComparison.swift
  3. 0 344
      Trio/Sources/APS/OpenAPSSwift/Logging/JSONCompare.swift
  4. 0 167
      Trio/Sources/APS/OpenAPSSwift/Logging/OrefFunction.swift
  5. 13 0
      Trio/Sources/APS/OpenAPSSwift/OrefFunctionResult.swift
  6. 0 363
      TrioTests/OpenAPSSwiftTests/AutosensJsonTests.swift
  7. 0 252
      TrioTests/OpenAPSSwiftTests/DetermineBasalJsonTests.swift
  8. 0 284
      TrioTests/OpenAPSSwiftTests/IobJsonTests.swift
  9. 0 214
      TrioTests/OpenAPSSwiftTests/JSONCompareTests.swift
  10. 0 167
      TrioTests/OpenAPSSwiftTests/MealJsonTests.swift
  11. 0 66
      TrioTests/OpenAPSSwiftTests/ProfileJavascriptTests.swift
  12. 0 265
      TrioTests/OpenAPSSwiftTests/ProfileJsNativeCompareTests.swift
  13. 0 93
      TrioTests/OpenAPSSwiftTests/ProfileJsonTests.swift
  14. 0 32
      TrioTests/OpenAPSSwiftTests/javascript/bundle/autosens-prepare-24.js
  15. 0 32
      TrioTests/OpenAPSSwiftTests/javascript/bundle/autosens-prepare-8.js
  16. 0 33
      TrioTests/OpenAPSSwiftTests/javascript/bundle/autosens-prepare.js
  17. 0 2
      TrioTests/OpenAPSSwiftTests/javascript/bundle/autosens.js
  18. 0 1
      TrioTests/OpenAPSSwiftTests/javascript/bundle/autotune-core.js
  19. 0 2
      TrioTests/OpenAPSSwiftTests/javascript/bundle/autotune-prep.js
  20. 0 1
      TrioTests/OpenAPSSwiftTests/javascript/bundle/basal-set-temp.js
  21. 0 51
      TrioTests/OpenAPSSwiftTests/javascript/bundle/determine-basal-prepare.js
  22. 0 1
      TrioTests/OpenAPSSwiftTests/javascript/bundle/determine-basal.js
  23. 0 1
      TrioTests/OpenAPSSwiftTests/javascript/bundle/glucose-get-last.js
  24. 0 1
      TrioTests/OpenAPSSwiftTests/javascript/bundle/iob-calculate.js
  25. 0 13
      TrioTests/OpenAPSSwiftTests/javascript/bundle/iob-history-prepare.js
  26. 0 2
      TrioTests/OpenAPSSwiftTests/javascript/bundle/iob-history.js
  27. 0 1
      TrioTests/OpenAPSSwiftTests/javascript/bundle/iob-total.js
  28. 0 2
      TrioTests/OpenAPSSwiftTests/javascript/bundle/iob.js
  29. 0 51
      TrioTests/OpenAPSSwiftTests/javascript/bundle/meal-prepare.js
  30. 0 2
      TrioTests/OpenAPSSwiftTests/javascript/bundle/meal.js
  31. 0 113
      TrioTests/OpenAPSSwiftTests/javascript/bundle/profile-prepare.js
  32. 0 2
      TrioTests/OpenAPSSwiftTests/javascript/bundle/profile.js
  33. 0 42
      TrioTests/OpenAPSSwiftTests/utils/HttpFiles.swift
  34. 0 162
      TrioTests/OpenAPSSwiftTests/utils/IobJsonTypes.swift
  35. 0 292
      TrioTests/OpenAPSSwiftTests/utils/OpenAPSFixed.swift
  36. 0 73
      TrioTests/OpenAPSSwiftTests/utils/ReplayTests.swift
  37. 0 42
      TrioTests/OpenAPSSwiftTests/utils/TimeZoneForTests.swift

+ 4 - 177
Trio.xcodeproj/project.pbxproj

@@ -203,7 +203,6 @@
 		38FEF413273B317A00574A46 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38FEF412273B317A00574A46 /* HKUnit.swift */; };
 		3B0B4E6C2DE1439F005C6627 /* LockedResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B0B4E6B2DE1439A005C6627 /* LockedResolver.swift */; };
 		3B139EF32DF06CE100D40797 /* AutosensGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B139EF22DF06CDC00D40797 /* AutosensGenerator.swift */; };
-		3B16C39C2DF75BD500C5C801 /* autosens-prepare.js in Resources */ = {isa = PBXBuildFile; fileRef = 3B16C39B2DF75BCB00C5C801 /* autosens-prepare.js */; };
 		3B1C5C292D68E1E3004E9273 /* IobCalculation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1C5C242D68E1E3004E9273 /* IobCalculation.swift */; };
 		3B1C5C2A2D68E1E3004E9273 /* IobGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1C5C262D68E1E3004E9273 /* IobGenerator.swift */; };
 		3B1C5C2B2D68E1E3004E9273 /* IobHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1C5C272D68E1E3004E9273 /* IobHistory.swift */; };
@@ -213,18 +212,15 @@
 		3B1C5C332D68E233004E9273 /* PumpHistory+copy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1C5C312D68E233004E9273 /* PumpHistory+copy.swift */; };
 		3B1C5C342D68E233004E9273 /* TimeExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1C5C322D68E233004E9273 /* TimeExtensions.swift */; };
 		3B1C5C432D68E269004E9273 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1C5C3D2D68E269004E9273 /* Extensions.swift */; };
-		3B1C5C442D68E269004E9273 /* IobJsonTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1C5C3E2D68E269004E9273 /* IobJsonTypes.swift */; };
 		3B1C5C452D68E269004E9273 /* IobTotalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1C5C382D68E269004E9273 /* IobTotalTests.swift */; };
 		3B1C5C472D68E269004E9273 /* IobCalculateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1C5C352D68E269004E9273 /* IobCalculateTests.swift */; };
 		3B1C5C482D68E269004E9273 /* IobHistoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1C5C362D68E269004E9273 /* IobHistoryTests.swift */; };
 		3B1DB90F2E63C14C00BD814B /* DetermineBasalLowEventualGlucoseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1DB90E2E63C14200BD814B /* DetermineBasalLowEventualGlucoseTests.swift */; };
-		3B214EEA2E29632900046304 /* determine-basal-prepare.js in Resources */ = {isa = PBXBuildFile; fileRef = 3B214EE92E29631F00046304 /* determine-basal-prepare.js */; };
 		3B2A3BC12E2B19C600658FB9 /* DynamicISF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2A3BC02E2B19C600658FB9 /* DynamicISF.swift */; };
 		3B2A3BC32E2B19F700658FB9 /* DynamicISFTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2A3BC22E2B19F700658FB9 /* DynamicISFTests.swift */; };
 		3B2CE68B2E24ADF7005EF782 /* IobGenerateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2CE68A2E24ADF3005EF782 /* IobGenerateTests.swift */; };
 		3B2F77862D7E52ED005ED9FA /* TDD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2F77852D7E52ED005ED9FA /* TDD.swift */; };
 		3B2F77882D7E5387005ED9FA /* CurrentTDDSetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2F77872D7E5387005ED9FA /* CurrentTDDSetup.swift */; };
-		3B31D5742E0E26C00047D32D /* ReplayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B31D5732E0E26BB0047D32D /* ReplayTests.swift */; };
 		3B3B4F542E661A1200B668E3 /* DetermineBasalGlucoseFallingFasterThanExpectedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3B4F532E6619FF00B668E3 /* DetermineBasalGlucoseFallingFasterThanExpectedTests.swift */; };
 		3B3B4F562E661FD600B668E3 /* DetermineBasalEventualOrForecastGlucoseLessThanMaxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3B4F552E661FC700B668E3 /* DetermineBasalEventualOrForecastGlucoseLessThanMaxTests.swift */; };
 		3B3B4F582E662B1E00B668E3 /* DetermineBasalIobGreaterThanMaxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3B4F572E662B1500B668E3 /* DetermineBasalIobGreaterThanMaxTests.swift */; };
@@ -232,7 +228,6 @@
 		3B4196E02D8C4BC00091DFF7 /* HomeStateModel+CGM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4196DF2D8C4BBB0091DFF7 /* HomeStateModel+CGM.swift */; };
 		3B4550532D862C0000551B0D /* PumpHistoryEvent+Duplicates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4550522D862BF200551B0D /* PumpHistoryEvent+Duplicates.swift */; };
 		3B47C6102DA0A28F00B0E5EF /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = 3B47C60F2DA0A28F00B0E5EF /* FirebaseCrashlytics */; };
-		3B4821822E080CAE00F0DD17 /* HttpFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4821812E080CAE00F0DD17 /* HttpFiles.swift */; };
 		3B4BA76A2D8DBD690069D5B8 /* CGMBLEKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B4BA75B2D8DBD690069D5B8 /* CGMBLEKit.framework */; };
 		3B4BA76B2D8DBD690069D5B8 /* CGMBLEKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B4BA75B2D8DBD690069D5B8 /* CGMBLEKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
 		3B4BA76C2D8DBD690069D5B8 /* CGMBLEKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B4BA75C2D8DBD690069D5B8 /* CGMBLEKitUI.framework */; };
@@ -294,8 +289,6 @@
 		3B5CD2CE2D4AECD500CE213C /* ProfileBasalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B5CD2C12D4AECD500CE213C /* ProfileBasalTests.swift */; };
 		3B5F45B62D6A239500F70982 /* DoubleApproximateMatching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B5F45B52D6A239000F70982 /* DoubleApproximateMatching.swift */; };
 		3B8221B22E5882E300585156 /* DetermineBasalEarlyExitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B8221B12E5882D900585156 /* DetermineBasalEarlyExitTests.swift */; };
-		3B8B5D3C2DF523C000365ED3 /* AutosensJsonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B8B5D3B2DF523B800365ED3 /* AutosensJsonTests.swift */; };
-		3B8B5D3E2DF5240C00365ED3 /* TimeZoneForTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B8B5D3D2DF5240600365ED3 /* TimeZoneForTests.swift */; };
 		3B997DCB2DC00849006B6BB2 /* JSONImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B997DCA2DC00849006B6BB2 /* JSONImporter.swift */; };
 		3B997DCF2DC00A3A006B6BB2 /* JSONImporterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B997DCE2DC00A3A006B6BB2 /* JSONImporterTests.swift */; };
 		3B997DD32DC02AEF006B6BB2 /* glucose.json in Resources */ = {isa = PBXBuildFile; fileRef = 3B997DD12DC02AEF006B6BB2 /* glucose.json */; };
@@ -311,46 +304,20 @@
 		3BAE87702E480BE100FCA8D2 /* ForecastResults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAE876F2E480BE100FCA8D2 /* ForecastResults.swift */; };
 		3BBB76AA2E01C70B0040977D /* MealCob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BBB76A92E01C7070040977D /* MealCob.swift */; };
 		3BBC22632DF5B94100169236 /* AutosensTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BBC22622DF5B93900169236 /* AutosensTests.swift */; };
-		3BBE323C2F12AB22005F9665 /* meal-prepare.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BBE323B2F12AB22005F9665 /* meal-prepare.js */; };
-		3BC0AA3B2DA74C87000DF7B7 /* iob-total.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BC0AA3A2DA74C87000DF7B7 /* iob-total.js */; };
-		3BC0AA3E2DA817EC000DF7B7 /* iob-calculate.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BC0AA3C2DA817EC000DF7B7 /* iob-calculate.js */; };
-		3BC0AA3F2DA817EC000DF7B7 /* iob-history.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BC0AA3D2DA817EC000DF7B7 /* iob-history.js */; };
-		3BC0AA412DA8B900000DF7B7 /* iob-history-prepare.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BC0AA402DA8B8F7000DF7B7 /* iob-history-prepare.js */; };
 		3BC26E552D7418830066ACD6 /* IobSuspendTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC26E542D7418830066ACD6 /* IobSuspendTests.swift */; };
-		3BC4053B2D931620006A03E9 /* IobJsonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC4053A2D931620006A03E9 /* IobJsonTests.swift */; };
 		3BCA5F7C2DC7B16400A7EAC7 /* pumphistory-with-external.json in Resources */ = {isa = PBXBuildFile; fileRef = 3BCA5F7B2DC7B15400A7EAC7 /* pumphistory-with-external.json */; };
-		3BCDDD312F219AF900496A94 /* ProfileJsonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BCDDD302F219AF300496A94 /* ProfileJsonTests.swift */; };
-		3BCDDD772F21A5F300496A94 /* profile-prepare.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BCDDD762F21A5F300496A94 /* profile-prepare.js */; };
 		3BCE75B32D4B38AE009E9453 /* InsulinSensitivities+Convert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BCE75B22D4B38A0009E9453 /* InsulinSensitivities+Convert.swift */; };
 		3BCE75B52D4B391F009E9453 /* Decimal+rounding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BCE75B42D4B3917009E9453 /* Decimal+rounding.swift */; };
-		3BD433AE2F01CDE600897F7D /* autosens-prepare-24.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BD433AD2F01CDD900897F7D /* autosens-prepare-24.js */; };
-		3BD433B02F01CDF500897F7D /* autosens-prepare-8.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BD433AF2F01CDEC00897F7D /* autosens-prepare-8.js */; };
 		3BD6CE262DC24CFD00FA0472 /* pumphistory-24h-zoned.json in Resources */ = {isa = PBXBuildFile; fileRef = 3BD6CE252DC24CFD00FA0472 /* pumphistory-24h-zoned.json */; };
 		3BD9687C2D8DDD4600899469 /* SlideButton in Frameworks */ = {isa = PBXBuildFile; productRef = 3BD9687B2D8DDD4600899469 /* SlideButton */; };
 		3BD9687F2D8DDD8800899469 /* CryptoSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 3BD9687E2D8DDD8800899469 /* CryptoSwift */; };
 		3BE2F1E82E030E2F009E2900 /* MealCobTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BE2F1E72E030E2F009E2900 /* MealCobTests.swift */; };
 		3BE2F1EA2E031951009E2900 /* MealCobBucketingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BE2F1E92E031951009E2900 /* MealCobBucketingTests.swift */; };
-		3BE9F0BB2E28C99B001B14EB /* DetermineBasalJsonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BE9F0BA2E28C993001B14EB /* DetermineBasalJsonTests.swift */; };
-		3BEA3AE02D58F79700A67A1D /* OrefFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BEA3ADE2D58F79700A67A1D /* OrefFunction.swift */; };
-		3BEA3AE12D58F79700A67A1D /* AlgorithmComparison.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BEA3ADB2D58F79700A67A1D /* AlgorithmComparison.swift */; };
-		3BEA3AE32D58F79700A67A1D /* JSONCompare.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BEA3ADC2D58F79700A67A1D /* JSONCompare.swift */; };
+		3BEA3AE02D58F79700A67A1D /* OrefFunctionResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BEA3ADE2D58F79700A67A1D /* OrefFunctionResult.swift */; };
 		3BEDC9932EEB27B600AC6492 /* IobConsecutiveEventsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BEDC9922EEB27B600AC6492 /* IobConsecutiveEventsTests.swift */; };
 		3BEF6AB12D9731660076089D /* MealHistoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BEF6AB02D9731530076089D /* MealHistoryTests.swift */; };
 		3BEF6AB32D97316F0076089D /* MealTotalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BEF6AB22D97316A0076089D /* MealTotalTests.swift */; };
-		3BEF6AB72D9750780076089D /* MealJsonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BEF6AB62D9750710076089D /* MealJsonTests.swift */; };
 		3BF424C72DF4805A0017CFD9 /* AutosensError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF424C62DF480550017CFD9 /* AutosensError.swift */; };
-		3BF8D0C12D5175BE001B3F84 /* ProfileJsNativeCompareTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF8D0C02D5175B3001B3F84 /* ProfileJsNativeCompareTests.swift */; };
-		3BF8D14B2D530397001B3F84 /* JSONCompareTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF8D14A2D530397001B3F84 /* JSONCompareTests.swift */; };
-		3BF92F2D2D86DEE9006B545A /* autosens.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BF92F212D86DEE9006B545A /* autosens.js */; };
-		3BF92F2E2D86DEE9006B545A /* autotune-prep.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BF92F232D86DEE9006B545A /* autotune-prep.js */; };
-		3BF92F2F2D86DEE9006B545A /* profile.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BF92F2A2D86DEE9006B545A /* profile.js */; };
-		3BF92F302D86DEE9006B545A /* determine-basal.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BF92F252D86DEE9006B545A /* determine-basal.js */; };
-		3BF92F312D86DEE9006B545A /* meal.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BF92F292D86DEE9006B545A /* meal.js */; };
-		3BF92F322D86DEE9006B545A /* glucose-get-last.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BF92F262D86DEE9006B545A /* glucose-get-last.js */; };
-		3BF92F332D86DEE9006B545A /* iob.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BF92F272D86DEE9006B545A /* iob.js */; };
-		3BF92F352D86DEE9006B545A /* basal-set-temp.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BF92F242D86DEE9006B545A /* basal-set-temp.js */; };
-		3BF92F362D86DEE9006B545A /* autotune-core.js in Resources */ = {isa = PBXBuildFile; fileRef = 3BF92F222D86DEE9006B545A /* autotune-core.js */; };
-		3BF92F382D86E10B006B545A /* OpenAPSFixed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF92F372D86E106006B545A /* OpenAPSFixed.swift */; };
 		3BF92F3A2D86F1AA006B545A /* iob-error-log.json in Resources */ = {isa = PBXBuildFile; fileRef = 3BF92F392D86F1AA006B545A /* iob-error-log.json */; };
 		3E28F2AB2EB5337F00FB9EEB /* ConnectIQ in Frameworks */ = {isa = PBXBuildFile; productRef = 3E28F2AA2EB5337F00FB9EEB /* ConnectIQ */; };
 		3E54EF2C2E476DA40006F54D /* MedtrumKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E54EF2B2E476DA40006F54D /* MedtrumKit.framework */; };
@@ -1176,7 +1143,6 @@
 		38FEF412273B317A00574A46 /* HKUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = "<group>"; };
 		3B0B4E6B2DE1439A005C6627 /* LockedResolver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockedResolver.swift; sourceTree = "<group>"; };
 		3B139EF22DF06CDC00D40797 /* AutosensGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutosensGenerator.swift; sourceTree = "<group>"; };
-		3B16C39B2DF75BCB00C5C801 /* autosens-prepare.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "autosens-prepare.js"; sourceTree = "<group>"; };
 		3B1C5C242D68E1E3004E9273 /* IobCalculation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IobCalculation.swift; sourceTree = "<group>"; };
 		3B1C5C252D68E1E3004E9273 /* IobError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IobError.swift; sourceTree = "<group>"; };
 		3B1C5C262D68E1E3004E9273 /* IobGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IobGenerator.swift; sourceTree = "<group>"; };
@@ -1189,22 +1155,18 @@
 		3B1C5C362D68E269004E9273 /* IobHistoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IobHistoryTests.swift; sourceTree = "<group>"; };
 		3B1C5C382D68E269004E9273 /* IobTotalTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IobTotalTests.swift; sourceTree = "<group>"; };
 		3B1C5C3D2D68E269004E9273 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
-		3B1C5C3E2D68E269004E9273 /* IobJsonTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IobJsonTypes.swift; sourceTree = "<group>"; };
 		3B1DB90E2E63C14200BD814B /* DetermineBasalLowEventualGlucoseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetermineBasalLowEventualGlucoseTests.swift; sourceTree = "<group>"; };
-		3B214EE92E29631F00046304 /* determine-basal-prepare.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "determine-basal-prepare.js"; sourceTree = "<group>"; };
 		3B2A3BC02E2B19C600658FB9 /* DynamicISF.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicISF.swift; sourceTree = "<group>"; };
 		3B2A3BC22E2B19F700658FB9 /* DynamicISFTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicISFTests.swift; sourceTree = "<group>"; };
 		3B2CE68A2E24ADF3005EF782 /* IobGenerateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IobGenerateTests.swift; sourceTree = "<group>"; };
 		3B2F77852D7E52ED005ED9FA /* TDD.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TDD.swift; sourceTree = "<group>"; };
 		3B2F77872D7E5387005ED9FA /* CurrentTDDSetup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentTDDSetup.swift; sourceTree = "<group>"; };
-		3B31D5732E0E26BB0047D32D /* ReplayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplayTests.swift; sourceTree = "<group>"; };
 		3B3B4F532E6619FF00B668E3 /* DetermineBasalGlucoseFallingFasterThanExpectedTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetermineBasalGlucoseFallingFasterThanExpectedTests.swift; sourceTree = "<group>"; };
 		3B3B4F552E661FC700B668E3 /* DetermineBasalEventualOrForecastGlucoseLessThanMaxTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetermineBasalEventualOrForecastGlucoseLessThanMaxTests.swift; sourceTree = "<group>"; };
 		3B3B4F572E662B1500B668E3 /* DetermineBasalIobGreaterThanMaxTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetermineBasalIobGreaterThanMaxTests.swift; sourceTree = "<group>"; };
 		3B3B57C82DA07B3400849D16 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
 		3B4196DF2D8C4BBB0091DFF7 /* HomeStateModel+CGM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeStateModel+CGM.swift"; sourceTree = "<group>"; };
 		3B4550522D862BF200551B0D /* PumpHistoryEvent+Duplicates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PumpHistoryEvent+Duplicates.swift"; sourceTree = "<group>"; };
-		3B4821812E080CAE00F0DD17 /* HttpFiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HttpFiles.swift; sourceTree = "<group>"; };
 		3B4BA75B2D8DBD690069D5B8 /* CGMBLEKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CGMBLEKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		3B4BA75C2D8DBD690069D5B8 /* CGMBLEKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CGMBLEKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		3B4BA75D2D8DBD690069D5B8 /* DanaKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DanaKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1245,8 +1207,6 @@
 		3B5CD2C62D4AECD500CE213C /* ProfileTargetsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileTargetsTests.swift; sourceTree = "<group>"; };
 		3B5F45B52D6A239000F70982 /* DoubleApproximateMatching.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleApproximateMatching.swift; sourceTree = "<group>"; };
 		3B8221B12E5882D900585156 /* DetermineBasalEarlyExitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetermineBasalEarlyExitTests.swift; sourceTree = "<group>"; };
-		3B8B5D3B2DF523B800365ED3 /* AutosensJsonTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutosensJsonTests.swift; sourceTree = "<group>"; };
-		3B8B5D3D2DF5240600365ED3 /* TimeZoneForTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeZoneForTests.swift; sourceTree = "<group>"; };
 		3B997DCA2DC00849006B6BB2 /* JSONImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONImporter.swift; sourceTree = "<group>"; };
 		3B997DCE2DC00A3A006B6BB2 /* JSONImporterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONImporterTests.swift; sourceTree = "<group>"; };
 		3B997DD12DC02AEF006B6BB2 /* glucose.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = glucose.json; sourceTree = "<group>"; };
@@ -1262,46 +1222,20 @@
 		3BAE876F2E480BE100FCA8D2 /* ForecastResults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastResults.swift; sourceTree = "<group>"; };
 		3BBB76A92E01C7070040977D /* MealCob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MealCob.swift; sourceTree = "<group>"; };
 		3BBC22622DF5B93900169236 /* AutosensTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutosensTests.swift; sourceTree = "<group>"; };
-		3BBE323B2F12AB22005F9665 /* meal-prepare.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "meal-prepare.js"; sourceTree = "<group>"; };
-		3BC0AA3A2DA74C87000DF7B7 /* iob-total.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "iob-total.js"; sourceTree = "<group>"; };
-		3BC0AA3C2DA817EC000DF7B7 /* iob-calculate.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "iob-calculate.js"; sourceTree = "<group>"; };
-		3BC0AA3D2DA817EC000DF7B7 /* iob-history.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "iob-history.js"; sourceTree = "<group>"; };
-		3BC0AA402DA8B8F7000DF7B7 /* iob-history-prepare.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "iob-history-prepare.js"; sourceTree = "<group>"; };
 		3BC26E542D7418830066ACD6 /* IobSuspendTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IobSuspendTests.swift; sourceTree = "<group>"; };
-		3BC4053A2D931620006A03E9 /* IobJsonTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IobJsonTests.swift; sourceTree = "<group>"; };
 		3BCA5F7B2DC7B15400A7EAC7 /* pumphistory-with-external.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "pumphistory-with-external.json"; sourceTree = "<group>"; };
-		3BCDDD302F219AF300496A94 /* ProfileJsonTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileJsonTests.swift; sourceTree = "<group>"; };
-		3BCDDD762F21A5F300496A94 /* profile-prepare.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "profile-prepare.js"; sourceTree = "<group>"; };
 		3BCE75B22D4B38A0009E9453 /* InsulinSensitivities+Convert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "InsulinSensitivities+Convert.swift"; sourceTree = "<group>"; };
 		3BCE75B42D4B3917009E9453 /* Decimal+rounding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Decimal+rounding.swift"; sourceTree = "<group>"; };
-		3BD433AD2F01CDD900897F7D /* autosens-prepare-24.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "autosens-prepare-24.js"; sourceTree = "<group>"; };
-		3BD433AF2F01CDEC00897F7D /* autosens-prepare-8.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "autosens-prepare-8.js"; sourceTree = "<group>"; };
 		3BD6CE252DC24CFD00FA0472 /* pumphistory-24h-zoned.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "pumphistory-24h-zoned.json"; sourceTree = "<group>"; };
 		3BDEA2DC60EDE0A3CA54DC73 /* TargetsEditorProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TargetsEditorProvider.swift; sourceTree = "<group>"; };
 		3BE2F1E72E030E2F009E2900 /* MealCobTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MealCobTests.swift; sourceTree = "<group>"; };
 		3BE2F1E92E031951009E2900 /* MealCobBucketingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MealCobBucketingTests.swift; sourceTree = "<group>"; };
-		3BE9F0BA2E28C993001B14EB /* DetermineBasalJsonTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetermineBasalJsonTests.swift; sourceTree = "<group>"; };
-		3BEA3ADB2D58F79700A67A1D /* AlgorithmComparison.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmComparison.swift; sourceTree = "<group>"; };
-		3BEA3ADC2D58F79700A67A1D /* JSONCompare.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONCompare.swift; sourceTree = "<group>"; };
-		3BEA3ADE2D58F79700A67A1D /* OrefFunction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrefFunction.swift; sourceTree = "<group>"; };
+		3BEA3ADE2D58F79700A67A1D /* OrefFunctionResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrefFunctionResult.swift; sourceTree = "<group>"; };
 		3BEDC9922EEB27B600AC6492 /* IobConsecutiveEventsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IobConsecutiveEventsTests.swift; sourceTree = "<group>"; };
 		3BEF6AB02D9731530076089D /* MealHistoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MealHistoryTests.swift; sourceTree = "<group>"; };
 		3BEF6AB22D97316A0076089D /* MealTotalTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MealTotalTests.swift; sourceTree = "<group>"; };
-		3BEF6AB62D9750710076089D /* MealJsonTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MealJsonTests.swift; sourceTree = "<group>"; };
 		3BF424C62DF480550017CFD9 /* AutosensError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutosensError.swift; sourceTree = "<group>"; };
 		3BF768BD6264FF7D71D66767 /* NightscoutConfigProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NightscoutConfigProvider.swift; sourceTree = "<group>"; };
-		3BF8D0C02D5175B3001B3F84 /* ProfileJsNativeCompareTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileJsNativeCompareTests.swift; sourceTree = "<group>"; };
-		3BF8D14A2D530397001B3F84 /* JSONCompareTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONCompareTests.swift; sourceTree = "<group>"; };
-		3BF92F212D86DEE9006B545A /* autosens.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = autosens.js; sourceTree = "<group>"; };
-		3BF92F222D86DEE9006B545A /* autotune-core.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "autotune-core.js"; sourceTree = "<group>"; };
-		3BF92F232D86DEE9006B545A /* autotune-prep.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "autotune-prep.js"; sourceTree = "<group>"; };
-		3BF92F242D86DEE9006B545A /* basal-set-temp.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "basal-set-temp.js"; sourceTree = "<group>"; };
-		3BF92F252D86DEE9006B545A /* determine-basal.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "determine-basal.js"; sourceTree = "<group>"; };
-		3BF92F262D86DEE9006B545A /* glucose-get-last.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "glucose-get-last.js"; sourceTree = "<group>"; };
-		3BF92F272D86DEE9006B545A /* iob.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = iob.js; sourceTree = "<group>"; };
-		3BF92F292D86DEE9006B545A /* meal.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = meal.js; sourceTree = "<group>"; };
-		3BF92F2A2D86DEE9006B545A /* profile.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = profile.js; sourceTree = "<group>"; };
-		3BF92F372D86E106006B545A /* OpenAPSFixed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenAPSFixed.swift; sourceTree = "<group>"; };
 		3BF92F392D86F1AA006B545A /* iob-error-log.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "iob-error-log.json"; sourceTree = "<group>"; };
 		3E54EF2B2E476DA40006F54D /* MedtrumKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MedtrumKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		3E62C7812F54CC1600433237 /* BolusDisplayThreshold.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusDisplayThreshold.swift; sourceTree = "<group>"; };
@@ -2619,43 +2553,27 @@
 				3870FF4225EC13F40088248F /* BloodGlucose.swift */,
 				38A9260425F012D8009E3739 /* CarbRatios.swift */,
 				38D0B3D825EC07C400CB6E88 /* CarbsEntry.swift */,
-				19D4E4EA29FC6A9F00351451 /* Charts.swift */,
 				DD6D67E32C9C253500660C9B /* ColorSchemeOption.swift */,
-				DD9ECB692CA99F6C00AA7C45 /* CommandPayload.swift */,
 				E592A36F2CEEC01E009A472C /* ContactTrickEntry.swift */,
 				3811DF0125CA9FEA00A708ED /* Credentials.swift */,
-				19A910352A24D6D700C8951B /* DateFilter.swift */,
-				DD21FCB42C6952AD00AF2C25 /* DecimalPickerSettings.swift */,
-				583684072BD195A700070A60 /* Determination.swift */,
-				DDD6D4D22CDE90720029439A /* EstimatedA1cDisplayUnit.swift */,
 				DD3D60302F0377350021A33B /* ExportSetting.swift */,
-				DD6B7CB32C7B71F700B75029 /* ForecastDisplayType.swift */,
 				DD3078692D42F94000DE0490 /* GarminDevice.swift */,
 				49090A8C2E9FE8D200D0F5DB /* GarminWatchSettings.swift */,
 				DD4FFF322D458EE600B6CFF9 /* GarminWatchState.swift */,
 				DD940BA92CA7585D000830A5 /* GlucoseColorScheme.swift */,
 				715120D12D3C2B84005D9FB6 /* GlucoseNotificationsOption.swift */,
 				E0D4F80427513ECF00BDF1FE /* HealthKitSample.swift */,
-				1967DFBD29D052C200759F30 /* Icons.swift */,
 				382C133625F13A1E00715CE1 /* InsulinSensitivities.swift */,
 				38887CCD25F5725200944304 /* IOBEntry.swift */,
-				BDF530D72B40F8AC002CAF43 /* LockScreenView.swift */,
-				193F6CDC2A512C8F001240FD /* Loops.swift */,
-				19012CDB291D2CB900FB8210 /* LoopStats.swift */,
 				DD68889C2C386E17006E3C44 /* NightscoutExercise.swift */,
-				FE41E4D529463EE20047FD55 /* NightscoutPreferences.swift */,
-				191F62672AD6B05A004D7911 /* NightscoutSettings.swift */,
 				385CEA8125F23DFD002D6D5B /* NightscoutStatus.swift */,
 				389442CA25F65F7100FA1F27 /* NightscoutTreatment.swift */,
-				BDC2EA462C3045AD00E5BBD0 /* Override.swift */,
 				BD54A95A2D28087700F9C1EE /* OverridePresetWatch.swift */,
 				3895E4C525B9E00D00214B37 /* Preferences.swift */,
 				38A13D3125E28B4B00EAA382 /* PumpHistoryEvent.swift */,
 				3883583325EEB38000E024B2 /* PumpSettings.swift */,
 				38E989DC25F5021400C0CED0 /* PumpStatus.swift */,
-				CC6C406D2ACDD69E009B8058 /* RawFetchedProfile.swift */,
 				38BF021C25E7E3AF00579895 /* Reservoir.swift */,
-				19B0EF2028F6D66200069496 /* Statistics.swift */,
 				3B2F77852D7E52ED005ED9FA /* TDD.swift */,
 				38A0364125ED069400FCBB52 /* TempBasal.swift */,
 				3871F39B25ED892B0013ECB5 /* TempTarget.swift */,
@@ -2668,7 +2586,6 @@
 				BD432CA02D2F4E3300D1EB79 /* WatchMessageKeys.swift */,
 				BDA25EFC2D261BF200035F34 /* WatchState.swift */,
 				DDFF204F2DB2C11900AB8A96 /* WatchStateSnapshot.swift */,
-				CE82E02628E869DF00473A9C /* AlertEntry.swift */,
 				19B0EF2028F6D66200069496 /* Statistics.swift */,
 				19012CDB291D2CB900FB8210 /* LoopStats.swift */,
 				FE41E4D529463EE20047FD55 /* NightscoutPreferences.swift */,
@@ -2918,11 +2835,6 @@
 			isa = PBXGroup;
 			children = (
 				3B1C5C3D2D68E269004E9273 /* Extensions.swift */,
-				3B4821812E080CAE00F0DD17 /* HttpFiles.swift */,
-				3B1C5C3E2D68E269004E9273 /* IobJsonTypes.swift */,
-				3BF92F372D86E106006B545A /* OpenAPSFixed.swift */,
-				3B31D5732E0E26BB0047D32D /* ReplayTests.swift */,
-				3B8B5D3D2DF5240600365ED3 /* TimeZoneForTests.swift */,
 			);
 			path = utils;
 			sourceTree = "<group>";
@@ -2943,12 +2855,12 @@
 				3B139EF12DF06CD100D40797 /* Autosens */,
 				3B5CD2A42D4AEA5D00CE213C /* Extensions */,
 				3B1C5C282D68E1E3004E9273 /* Iob */,
-				3BEA3ADF2D58F79700A67A1D /* Logging */,
 				DD9E6DA02D59A11200514CEC /* Meal */,
 				3B5CD2B22D4AEA6600CE213C /* Models */,
 				3B5CD2972D4AEA3C00CE213C /* Profile */,
 				3B5CD2A02D4AEA5100CE213C /* Utils */,
 				3B5CD1E92D4912A600CE213C /* OpenAPSSwift.swift */,
+				3BEA3ADE2D58F79700A67A1D /* OrefFunctionResult.swift */,
 				3B5CD1EA2D4912A600CE213C /* JSONBridge.swift */,
 			);
 			path = OpenAPSSwift;
@@ -3010,10 +2922,8 @@
 		3B5CD2C72D4AECD500CE213C /* OpenAPSSwiftTests */ = {
 			isa = PBXGroup;
 			children = (
-				3BF92F2C2D86DEE9006B545A /* javascript */,
 				3B1C5C3C2D68E269004E9273 /* json */,
 				3B1C5C3F2D68E269004E9273 /* utils */,
-				3B8B5D3B2DF523B800365ED3 /* AutosensJsonTests.swift */,
 				3BBC22622DF5B93900169236 /* AutosensTests.swift */,
 				3BA643E92ED9FAD8007BC31F /* DetermineBasalAggressiveDosingTests.swift */,
 				DD30B9FF2E0745C400DA677C /* DetermineBasalDeltaCalculationTests.swift */,
@@ -3022,7 +2932,6 @@
 				3B3B4F552E661FC700B668E3 /* DetermineBasalEventualOrForecastGlucoseLessThanMaxTests.swift */,
 				3B3B4F532E6619FF00B668E3 /* DetermineBasalGlucoseFallingFasterThanExpectedTests.swift */,
 				3B3B4F572E662B1500B668E3 /* DetermineBasalIobGreaterThanMaxTests.swift */,
-				3BE9F0BA2E28C993001B14EB /* DetermineBasalJsonTests.swift */,
 				3B1DB90E2E63C14200BD814B /* DetermineBasalLowEventualGlucoseTests.swift */,
 				DD758EDD2ECC656500EF5D54 /* DetermineBasalSmbMicroBolusTests.swift */,
 				3B2A3BC22E2B19F700658FB9 /* DynamicISFTests.swift */,
@@ -3030,20 +2939,15 @@
 				3BEDC9922EEB27B600AC6492 /* IobConsecutiveEventsTests.swift */,
 				3B2CE68A2E24ADF3005EF782 /* IobGenerateTests.swift */,
 				3B1C5C362D68E269004E9273 /* IobHistoryTests.swift */,
-				3BC4053A2D931620006A03E9 /* IobJsonTests.swift */,
 				3BC26E542D7418830066ACD6 /* IobSuspendTests.swift */,
 				3B1C5C382D68E269004E9273 /* IobTotalTests.swift */,
-				3BF8D14A2D530397001B3F84 /* JSONCompareTests.swift */,
 				3BE2F1E92E031951009E2900 /* MealCobBucketingTests.swift */,
 				3BE2F1E72E030E2F009E2900 /* MealCobTests.swift */,
 				3BEF6AB02D9731530076089D /* MealHistoryTests.swift */,
-				3BEF6AB62D9750710076089D /* MealJsonTests.swift */,
 				3BEF6AB22D97316A0076089D /* MealTotalTests.swift */,
-				3BF8D0C02D5175B3001B3F84 /* ProfileJsNativeCompareTests.swift */,
 				3B5CD2C12D4AECD500CE213C /* ProfileBasalTests.swift */,
 				3B5CD2C32D4AECD500CE213C /* ProfileCarbsTests.swift */,
 				3B5CD2C42D4AECD500CE213C /* ProfileIsfTests.swift */,
-				3BCDDD302F219AF300496A94 /* ProfileJsonTests.swift */,
 				3B5CD2C52D4AECD500CE213C /* ProfileJavascriptTests.swift */,
 				3B5CD2C62D4AECD500CE213C /* ProfileTargetsTests.swift */,
 				3BAC92CC2E57859600B853DA /* SetTempBasalTests.swift */,
@@ -3065,50 +2969,6 @@
 			path = JSONImporterData;
 			sourceTree = "<group>";
 		};
-		3BEA3ADF2D58F79700A67A1D /* Logging */ = {
-			isa = PBXGroup;
-			children = (
-				3BEA3ADB2D58F79700A67A1D /* AlgorithmComparison.swift */,
-				3BEA3ADC2D58F79700A67A1D /* JSONCompare.swift */,
-				3BEA3ADE2D58F79700A67A1D /* OrefFunction.swift */,
-			);
-			path = Logging;
-			sourceTree = "<group>";
-		};
-		3BF92F2B2D86DEE9006B545A /* bundle */ = {
-			isa = PBXGroup;
-			children = (
-				3B214EE92E29631F00046304 /* determine-basal-prepare.js */,
-				3B16C39B2DF75BCB00C5C801 /* autosens-prepare.js */,
-				3BD433AF2F01CDEC00897F7D /* autosens-prepare-8.js */,
-				3BD433AD2F01CDD900897F7D /* autosens-prepare-24.js */,
-				3BC0AA402DA8B8F7000DF7B7 /* iob-history-prepare.js */,
-				3BF92F212D86DEE9006B545A /* autosens.js */,
-				3BF92F222D86DEE9006B545A /* autotune-core.js */,
-				3BF92F232D86DEE9006B545A /* autotune-prep.js */,
-				3BF92F242D86DEE9006B545A /* basal-set-temp.js */,
-				3BF92F252D86DEE9006B545A /* determine-basal.js */,
-				3BF92F262D86DEE9006B545A /* glucose-get-last.js */,
-				3BF92F272D86DEE9006B545A /* iob.js */,
-				3BC0AA3C2DA817EC000DF7B7 /* iob-calculate.js */,
-				3BC0AA3D2DA817EC000DF7B7 /* iob-history.js */,
-				3BC0AA3A2DA74C87000DF7B7 /* iob-total.js */,
-				3BF92F292D86DEE9006B545A /* meal.js */,
-				3BBE323B2F12AB22005F9665 /* meal-prepare.js */,
-				3BF92F2A2D86DEE9006B545A /* profile.js */,
-				3BCDDD762F21A5F300496A94 /* profile-prepare.js */,
-			);
-			path = bundle;
-			sourceTree = "<group>";
-		};
-		3BF92F2C2D86DEE9006B545A /* javascript */ = {
-			isa = PBXGroup;
-			children = (
-				3BF92F2B2D86DEE9006B545A /* bundle */,
-			);
-			path = javascript;
-			sourceTree = "<group>";
-		};
 		4E8C7B59F8065047ECE20965 /* View */ = {
 			isa = PBXGroup;
 			children = (
@@ -4541,32 +4401,13 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3BF92F2D2D86DEE9006B545A /* autosens.js in Resources */,
-				3BF92F2E2D86DEE9006B545A /* autotune-prep.js in Resources */,
-				3BBE323C2F12AB22005F9665 /* meal-prepare.js in Resources */,
-				3BF92F2F2D86DEE9006B545A /* profile.js in Resources */,
-				3BF92F302D86DEE9006B545A /* determine-basal.js in Resources */,
-				3BD433AE2F01CDE600897F7D /* autosens-prepare-24.js in Resources */,
-				3BF92F312D86DEE9006B545A /* meal.js in Resources */,
-				3BF92F322D86DEE9006B545A /* glucose-get-last.js in Resources */,
-				3BF92F332D86DEE9006B545A /* iob.js in Resources */,
-				3BF92F352D86DEE9006B545A /* basal-set-temp.js in Resources */,
-				3BF92F362D86DEE9006B545A /* autotune-core.js in Resources */,
-				3BC0AA3B2DA74C87000DF7B7 /* iob-total.js in Resources */,
-				3B214EEA2E29632900046304 /* determine-basal-prepare.js in Resources */,
-				3BC0AA3E2DA817EC000DF7B7 /* iob-calculate.js in Resources */,
-				3BC0AA3F2DA817EC000DF7B7 /* iob-history.js in Resources */,
-				3BC0AA412DA8B900000DF7B7 /* iob-history-prepare.js in Resources */,
 				3BF92F3A2D86F1AA006B545A /* iob-error-log.json in Resources */,
 				3BD6CE262DC24CFD00FA0472 /* pumphistory-24h-zoned.json in Resources */,
 				DDD78A912DC4064800AC63F3 /* carbhistory.json in Resources */,
 				3B997DD32DC02AEF006B6BB2 /* glucose.json in Resources */,
-				3BCDDD772F21A5F300496A94 /* profile-prepare.js in Resources */,
-				3BD433B02F01CDF500897F7D /* autosens-prepare-8.js in Resources */,
 				DDD78AD92DC421B500AC63F3 /* enacted.json in Resources */,
 				DD3C47B32DC5608A003DD20D /* newerSuggested.json in Resources */,
 				3BCA5F7C2DC7B16400A7EAC7 /* pumphistory-with-external.json in Resources */,
-				3B16C39C2DF75BD500C5C801 /* autosens-prepare.js in Resources */,
 				DDD78ADA2DC421B500AC63F3 /* suggested.json in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -4903,9 +4744,7 @@
 				582DF97B2C8CE209001F516D /* CarbView.swift in Sources */,
 				DD940BAA2CA7585D000830A5 /* GlucoseColorScheme.swift in Sources */,
 				3811DE2225C9D48300A708ED /* MainProvider.swift in Sources */,
-				3BEA3AE02D58F79700A67A1D /* OrefFunction.swift in Sources */,
-				3BEA3AE12D58F79700A67A1D /* AlgorithmComparison.swift in Sources */,
-				3BEA3AE32D58F79700A67A1D /* JSONCompare.swift in Sources */,
+				3BEA3AE02D58F79700A67A1D /* OrefFunctionResult.swift in Sources */,
 				BD47FD1B2D88AB4F0043966B /* OnboardingStateModel.swift in Sources */,
 				3811DE0C25C9D32F00A708ED /* BaseProvider.swift in Sources */,
 				CE95BF5A2BA62E4A00DC3DE3 /* PluginSource.swift in Sources */,
@@ -5330,7 +5169,6 @@
 			files = (
 				3B5CD2C92D4AECD500CE213C /* ProfileCarbsTests.swift in Sources */,
 				3BEDC9932EEB27B600AC6492 /* IobConsecutiveEventsTests.swift in Sources */,
-				3B8B5D3E2DF5240C00365ED3 /* TimeZoneForTests.swift in Sources */,
 				3B1DB90F2E63C14C00BD814B /* DetermineBasalLowEventualGlucoseTests.swift in Sources */,
 				3B5CD2CA2D4AECD500CE213C /* ProfileJavascriptTests.swift in Sources */,
 				3B3B4F542E661A1200B668E3 /* DetermineBasalGlucoseFallingFasterThanExpectedTests.swift in Sources */,
@@ -5340,10 +5178,8 @@
 				3B5CD2CE2D4AECD500CE213C /* ProfileBasalTests.swift in Sources */,
 				3B3B4F582E662B1E00B668E3 /* DetermineBasalIobGreaterThanMaxTests.swift in Sources */,
 				CEE9A65E2BBC9F6500EB5194 /* CalibrationsTests.swift in Sources */,
-				3BF8D14B2D530397001B3F84 /* JSONCompareTests.swift in Sources */,
 				3B3B4F562E661FD600B668E3 /* DetermineBasalEventualOrForecastGlucoseLessThanMaxTests.swift in Sources */,
 				3BEF6AB32D97316F0076089D /* MealTotalTests.swift in Sources */,
-				3BF8D0C12D5175BE001B3F84 /* ProfileJsNativeCompareTests.swift in Sources */,
 				3BEF6AB12D9731660076089D /* MealHistoryTests.swift in Sources */,
 				BD8FC0572D66188700B95AED /* PumpHistoryStorageTests.swift in Sources */,
 				BD8FC0642D6619EF00B95AED /* TempTargetStorageTests.swift in Sources */,
@@ -5355,13 +5191,9 @@
 				BD8FC0622D6619E600B95AED /* OverrideStorageTests.swift in Sources */,
 				BD8FC0592D66189700B95AED /* TestAssembly.swift in Sources */,
 				DDC6CA6D2DD90A2A0060EE25 /* LocalizationTests.swift in Sources */,
-				3BE9F0BB2E28C99B001B14EB /* DetermineBasalJsonTests.swift in Sources */,
 				3B997DCF2DC00A3A006B6BB2 /* JSONImporterTests.swift in Sources */,
-				3B31D5742E0E26C00047D32D /* ReplayTests.swift in Sources */,
-				3B8B5D3C2DF523C000365ED3 /* AutosensJsonTests.swift in Sources */,
 				3B2A3BC32E2B19F700658FB9 /* DynamicISFTests.swift in Sources */,
 				BD8FC0662D661A0000B95AED /* GlucoseStorageTests.swift in Sources */,
-				3BCDDD312F219AF900496A94 /* ProfileJsonTests.swift in Sources */,
 				DDDD0FFF2F4E231B00F9C645 /* MockTDDStorage.swift in Sources */,
 				BD8FC05B2D6618AF00B95AED /* DeterminationStorageTests.swift in Sources */,
 				3BAAE60C2DE7766C0049589B /* DynamicISFEnableTests.swift in Sources */,
@@ -5369,17 +5201,12 @@
 				CE1F6DD92BADF4620064EB8D /* PluginManagerTests.swift in Sources */,
 				3B1C5C432D68E269004E9273 /* Extensions.swift in Sources */,
 				3BC26E552D7418830066ACD6 /* IobSuspendTests.swift in Sources */,
-				3BF92F382D86E10B006B545A /* OpenAPSFixed.swift in Sources */,
 				DD758EDE2ECC656500EF5D54 /* DetermineBasalSmbMicroBolusTests.swift in Sources */,
-				3B4821822E080CAE00F0DD17 /* HttpFiles.swift in Sources */,
-				3B1C5C442D68E269004E9273 /* IobJsonTypes.swift in Sources */,
 				3B1C5C452D68E269004E9273 /* IobTotalTests.swift in Sources */,
 				3BE2F1EA2E031951009E2900 /* MealCobBucketingTests.swift in Sources */,
 				3B1C5C472D68E269004E9273 /* IobCalculateTests.swift in Sources */,
 				3B2CE68B2E24ADF7005EF782 /* IobGenerateTests.swift in Sources */,
 				3B1C5C482D68E269004E9273 /* IobHistoryTests.swift in Sources */,
-				3BC4053B2D931620006A03E9 /* IobJsonTests.swift in Sources */,
-				3BEF6AB72D9750780076089D /* MealJsonTests.swift in Sources */,
 				38FCF3F925E902C20078B0D1 /* FileStorageTests.swift in Sources */,
 				3B8221B22E5882E300585156 /* DetermineBasalEarlyExitTests.swift in Sources */,
 				3BA643EA2ED9FAD8007BC31F /* DetermineBasalAggressiveDosingTests.swift in Sources */,

+ 0 - 202
Trio/Sources/APS/OpenAPSSwift/Logging/AlgorithmComparison.swift

@@ -1,202 +0,0 @@
-import Foundation
-
-/// After the port from Javascript to Swift is complete, we should remove the logging module:
-/// https://github.com/nightscout/Trio-dev/issues/293
-
-/// Represents an exception that occurred during algorithm execution
-struct AlgorithmException: Codable {
-    let message: String
-    let stackTrace: String?
-    let errorType: String?
-
-    init(message: String, stackTrace: String? = nil, errorType: String? = nil) {
-        self.message = message
-        self.stackTrace = stackTrace
-        self.errorType = errorType
-    }
-
-    init(error: Error) {
-        // Get the error message
-        if let localizedError = error as? LocalizedError {
-            message = localizedError.errorDescription ?? error.localizedDescription
-        } else {
-            message = error.localizedDescription
-        }
-
-        // Get error type
-        errorType = String(describing: type(of: error))
-
-        // Get stack trace if available
-        if let nsError = error as NSError? {
-            var traceComponents: [String] = []
-
-            // Add domain and code
-            traceComponents.append("Domain: \(nsError.domain)")
-            traceComponents.append("Code: \(nsError.code)")
-
-            // Add userInfo details
-            if !nsError.userInfo.isEmpty {
-                traceComponents.append("UserInfo: \(nsError.userInfo)")
-            }
-
-            // Add call stack
-            let callStackSymbols = Thread.callStackSymbols as [String]
-            if !callStackSymbols.isEmpty {
-                traceComponents.append("Call Stack:")
-                traceComponents.append(contentsOf: callStackSymbols)
-            }
-
-            stackTrace = traceComponents.isEmpty ? nil : traceComponents.joined(separator: "\n")
-        } else {
-            stackTrace = nil
-        }
-    }
-}
-
-/// Represents the type of comparison result
-enum ComparisonResultType: String, Codable {
-    case matching // Both implementations succeed with matching results
-    case valueDifference // Both implementations succeed but values differ
-    case matchingExceptions // Both implementations threw exceptions
-    case jsOnlyException // Only JS threw an exception
-    case swiftOnlyException // Only Swift threw an exception
-    case comparisonError // The comparison algorithm itself failed
-}
-
-/// For tracking inputs to IoB when there is a mismatch
-struct IobInputs: Codable {
-    let history: [PumpHistoryEvent]
-    let profile: Profile
-    let clock: Date
-    let autosens: Autosens?
-}
-
-/// For tracking inputs to `meal` when there is a mismatch
-struct MealInputs: Codable {
-    let pumpHistory: [PumpHistoryEvent]
-    let profile: Profile
-    let basalProfile: [BasalProfileEntry]
-    let clock: Date
-    let carbs: [CarbsEntry]
-    let glucose: [BloodGlucose]
-}
-
-/// For tracking inputs to Autosens when there is a mismatch
-struct AutosensInputs: Codable {
-    let glucose: [BloodGlucose]
-    let history: [PumpHistoryEvent]
-    let basalProfile: [BasalProfileEntry]
-    let profile: Profile
-    let carbs: [CarbsEntry]
-    let tempTargets: [TempTarget]
-    let clock: Date
-}
-
-/// For tracking inputs to `determineBasal` when there is a mismatch
-struct DetermineBasalInputs: Codable {
-    let glucose: [BloodGlucose]
-    let currentTemp: TempBasal
-    let iob: [IobResult]
-    let profile: Profile
-    let autosens: Autosens?
-    let meal: ComputedCarbs?
-    let microBolusAllowed: Bool
-    let reservoir: Decimal?
-    let pumpHistory: [PumpHistoryEvent]
-    let preferences: Preferences
-    let basalProfile: [BasalProfileEntry]
-    let trioCustomOrefVariables: TrioCustomOrefVariables
-    let clock: Date
-}
-
-/// For tracking inputs to `makeProfile` when there is a mismatch
-struct MakeProfileInputs: Codable {
-    let preferences: Preferences
-    let pumpSettings: PumpSettings
-    let bgTargets: BGTargets
-    let basalProfile: [BasalProfileEntry]
-    let isf: InsulinSensitivities
-    let carbRatios: CarbRatios
-    let tempTargets: [TempTarget]
-    let model: String
-    let trioSettings: TrioSettings
-    let clock: Date
-}
-
-/// Represents a complete comparison between JS and Swift implementations
-struct AlgorithmComparison: Codable {
-    let id: UUID
-    let createdAt: Date
-    let timezone: String
-    let function: OrefFunction
-    let resultType: ComparisonResultType
-
-    // Performance metrics (optional as they may not be available in error cases)
-    let jsDuration: TimeInterval?
-    let swiftDuration: TimeInterval?
-
-    // Value differences (present when resultType is .valueDifference)
-    let differences: [String: ValueDifference]?
-
-    // Exception information (present for various error cases)
-    let jsException: AlgorithmException?
-    let swiftException: AlgorithmException?
-    let comparisonError: AlgorithmException?
-    let version: String?
-    let isSimulator: Bool?
-    let isDebugBuild: Bool?
-
-    // Inputs for mismatches
-    let iobInput: IobInputs?
-    let mealInput: MealInputs?
-    let autosensInput: AutosensInputs?
-    let determineBasalInput: DetermineBasalInputs?
-    let makeProfileInput: MakeProfileInputs?
-
-    init(
-        function: OrefFunction,
-        resultType: ComparisonResultType,
-        jsDuration: TimeInterval? = nil,
-        swiftDuration: TimeInterval? = nil,
-        differences: [String: ValueDifference]? = nil,
-        jsException: AlgorithmException? = nil,
-        swiftException: AlgorithmException? = nil,
-        comparisonError: AlgorithmException? = nil,
-        iobInputs: IobInputs? = nil,
-        mealInputs: MealInputs? = nil,
-        autosensInputs: AutosensInputs? = nil,
-        determineBasalInputs: DetermineBasalInputs? = nil,
-        makeProfileInputs: MakeProfileInputs? = nil,
-        id: UUID = UUID(),
-        createdAt: Date = Date()
-    ) {
-        self.id = id
-        self.createdAt = createdAt
-        self.function = function
-        self.resultType = resultType
-        self.jsDuration = jsDuration
-        self.swiftDuration = swiftDuration
-        self.differences = differences
-        self.jsException = jsException
-        self.swiftException = swiftException
-        self.comparisonError = comparisonError
-        iobInput = iobInputs
-        mealInput = mealInputs
-        autosensInput = autosensInputs
-        determineBasalInput = determineBasalInputs
-        makeProfileInput = makeProfileInputs
-        timezone = TimeZone.current.identifier
-        version = "4"
-        #if targetEnvironment(simulator)
-            isSimulator = true
-        #else
-            isSimulator = false
-        #endif
-
-        #if DEBUG
-            isDebugBuild = true
-        #else
-            isDebugBuild = false
-        #endif
-    }
-}

+ 0 - 344
Trio/Sources/APS/OpenAPSSwift/Logging/JSONCompare.swift

@@ -1,344 +0,0 @@
-import Foundation
-
-enum JSONValue: Codable, Equatable {
-    case string(String)
-    case number(Double)
-    case boolean(Bool)
-    case array([JSONValue])
-    case object([String: JSONValue])
-    case null
-
-    init(from decoder: Decoder) throws {
-        let container = try decoder.singleValueContainer()
-
-        if container.decodeNil() {
-            self = .null
-            return
-        }
-
-        if let string = try? container.decode(String.self) {
-            self = .string(string)
-        } else if let number = try? container.decode(Double.self) {
-            self = .number(number)
-        } else if let boolean = try? container.decode(Bool.self) {
-            self = .boolean(boolean)
-        } else if let array = try? container.decode([JSONValue].self) {
-            self = .array(array)
-        } else if let object = try? container.decode([String: JSONValue].self) {
-            self = .object(object)
-        } else {
-            throw DecodingError.typeMismatch(JSONValue.self, DecodingError.Context(
-                codingPath: decoder.codingPath,
-                debugDescription: "Invalid JSON value"
-            ))
-        }
-    }
-
-    func encode(to encoder: Encoder) throws {
-        var container = encoder.singleValueContainer()
-        switch self {
-        case let .string(value): try container.encode(value)
-        case let .number(value): try container.encode(value)
-        case let .boolean(value): try container.encode(value)
-        case let .array(value): try container.encode(value)
-        case let .object(value): try container.encode(value)
-        case .null: try container.encodeNil()
-        }
-    }
-
-    static func == (lhs: JSONValue, rhs: JSONValue) -> Bool {
-        switch (lhs, rhs) {
-        case (.null, .null):
-            return true
-        case let (.string(lhs), .string(rhs)):
-            return lhs == rhs
-        case let (.number(lhs), .number(rhs)):
-            return lhs == rhs
-        case let (.boolean(lhs), .boolean(rhs)):
-            return lhs == rhs
-        case let (.array(lhs), .array(rhs)):
-            return lhs == rhs
-        case let (.object(lhs), .object(rhs)):
-            return lhs == rhs
-        default:
-            return false
-        }
-    }
-}
-
-struct ValueDifference: Codable {
-    let js: JSONValue
-    let swift: JSONValue
-    let jsKeyMissing: Bool
-    let nativeKeyMissing: Bool
-}
-
-enum JSONCompare {
-    static func createComparison(
-        function: OrefFunction,
-        swift: OrefFunctionResult,
-        swiftDuration: TimeInterval,
-        javascript: OrefFunctionResult,
-        javascriptDuration: TimeInterval,
-        iobInputs: IobInputs?,
-        mealInputs: MealInputs?,
-        autosensInputs: AutosensInputs?,
-        determineBasalInputs: DetermineBasalInputs?,
-        makeProfileInputs: MakeProfileInputs?
-    ) -> AlgorithmComparison {
-        switch (swift, javascript) {
-        case let (.success(swiftJson), .success(javascriptJson)):
-            do {
-                let differences = try differences(function: function, swift: swiftJson, javascript: javascriptJson)
-                let resultType: ComparisonResultType = differences.isEmpty ? .matching : .valueDifference
-                return AlgorithmComparison(
-                    function: function,
-                    resultType: resultType,
-                    jsDuration: javascriptDuration,
-                    swiftDuration: swiftDuration,
-                    differences: differences.isEmpty ? nil : differences,
-                    iobInputs: differences.isEmpty ? nil : iobInputs,
-                    mealInputs: differences.isEmpty ? nil : mealInputs,
-                    autosensInputs: differences.isEmpty ? nil : autosensInputs,
-                    determineBasalInputs: differences.isEmpty ? nil : determineBasalInputs,
-                    makeProfileInputs: differences.isEmpty ? nil : makeProfileInputs
-                )
-            } catch {
-                return AlgorithmComparison(
-                    function: function,
-                    resultType: .comparisonError,
-                    jsDuration: javascriptDuration,
-                    swiftDuration: swiftDuration,
-                    comparisonError: AlgorithmException(error: error),
-                    iobInputs: iobInputs,
-                    mealInputs: mealInputs,
-                    autosensInputs: autosensInputs,
-                    determineBasalInputs: determineBasalInputs,
-                    makeProfileInputs: makeProfileInputs
-                )
-            }
-
-        case let (.failure(swiftError), .failure(jsError)):
-            return AlgorithmComparison(
-                function: function,
-                resultType: .matchingExceptions,
-                jsException: AlgorithmException(error: jsError),
-                swiftException: AlgorithmException(error: swiftError)
-            )
-
-        case let (.failure(swiftError), .success):
-            return AlgorithmComparison(
-                function: function,
-                resultType: .swiftOnlyException,
-                jsDuration: javascriptDuration,
-                swiftException: AlgorithmException(error: swiftError),
-                iobInputs: iobInputs,
-                mealInputs: mealInputs,
-                autosensInputs: autosensInputs,
-                determineBasalInputs: determineBasalInputs,
-                makeProfileInputs: makeProfileInputs
-            )
-
-        case let (.success, .failure(jsError)):
-            return AlgorithmComparison(
-                function: function,
-                resultType: .jsOnlyException,
-                swiftDuration: swiftDuration,
-                jsException: AlgorithmException(error: jsError),
-                iobInputs: iobInputs,
-                mealInputs: mealInputs,
-                autosensInputs: autosensInputs,
-                determineBasalInputs: determineBasalInputs,
-                makeProfileInputs: makeProfileInputs
-            )
-        }
-    }
-
-    static func prettyPrint(_ differences: [String: ValueDifference]) {
-        let encoder = JSONEncoder()
-        encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
-
-        if let data = try? encoder.encode(differences),
-           let prettyString = String(data: data, encoding: .utf8)
-        {
-            debug(.openAPS, prettyString)
-        }
-    }
-
-    static func differences(function: OrefFunction, swift: String, javascript: String) throws -> [String: ValueDifference] {
-        let differences = try {
-            switch function.returnType() {
-            case .array:
-                return try differencesArray(function: function, swift: swift, javascript: javascript)
-            case .dictionary:
-                return try differencesDictionary(function: function, swift: swift, javascript: javascript)
-            }
-        }()
-
-        let keysToIgnore = function.keysToIgnore()
-        return differences.filter { !keysToIgnore.contains($0.key) }
-    }
-
-    private static func differencesArray(
-        function: OrefFunction,
-        swift: String,
-        javascript: String
-    ) throws -> [String: ValueDifference] {
-        guard let jsData = javascript.data(using: .utf8),
-              let swiftData = swift.data(using: .utf8),
-              let jsArray = try JSONSerialization.jsonObject(with: jsData) as? [Any],
-              let swiftArray = try JSONSerialization.jsonObject(with: swiftData) as? [Any]
-        else {
-            throw NSError(domain: "JSONBridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "Invalid JSON format"])
-        }
-
-        // Converting arrays into dictionaries for comparison
-        let jsDict = Dictionary(uniqueKeysWithValues: jsArray.enumerated().map { index, value in
-            ("[\(index)]", value)
-        })
-        let swiftDict = Dictionary(uniqueKeysWithValues: swiftArray.enumerated().map { index, value in
-            ("[\(index)]", value)
-        })
-
-        return compareDict(function: function, swiftDict: swiftDict, jsDict: jsDict)
-    }
-
-    private static func differencesDictionary(
-        function: OrefFunction,
-        swift: String,
-        javascript: String
-    ) throws -> [String: ValueDifference] {
-        guard let jsData = javascript.data(using: .utf8),
-              let swiftData = swift.data(using: .utf8),
-              let jsDict = try JSONSerialization.jsonObject(with: jsData) as? [String: Any],
-              let swiftDict = try JSONSerialization.jsonObject(with: swiftData) as? [String: Any]
-        else {
-            throw NSError(domain: "JSONBridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "Invalid JSON format"])
-        }
-
-        return compareDict(function: function, swiftDict: swiftDict, jsDict: jsDict)
-    }
-
-    private static func compareDict(
-        function: OrefFunction,
-        swiftDict: [String: Any],
-        jsDict: [String: Any],
-        path: String = ""
-    ) -> [String: ValueDifference] {
-        var differences: [String: ValueDifference] = [:]
-        let approximateKeys = function.approximateMatchingNumbers()
-        let flexibleArrayKeys = function.flexibleArrayKeys()
-        let propertiesToSkip = function.propertiesToSkip()
-
-        // Check all keys present in either dictionary
-        Set(jsDict.keys).union(swiftDict.keys).forEach { key in
-            let currentPath = path.isEmpty ? key : "\(path).\(key)"
-            let jsValue = jsDict[key].map(convertToJSONValue) ?? .null
-            let swiftValue = swiftDict[key].map(convertToJSONValue) ?? .null
-
-            if !valuesAreEqual(
-                jsValue, swiftValue,
-                approximately: approximateKeys[key],
-                approximateKeys: approximateKeys,
-                flexibleArrayKeys: flexibleArrayKeys,
-                propertiesToSkip: propertiesToSkip,
-                currentPath: currentPath
-            ) {
-                differences[currentPath] = ValueDifference(
-                    js: jsValue,
-                    swift: swiftValue,
-                    jsKeyMissing: !jsDict.keys.contains(key),
-                    nativeKeyMissing: !swiftDict.keys.contains(key)
-                )
-            }
-        }
-
-        return differences
-    }
-
-    private static func convertToJSONValue(_ value: Any) -> JSONValue {
-        switch value {
-        case let string as String:
-            return .string(string)
-        case let number as NSNumber:
-            // NSNumber can represent both booleans and numbers
-            // Check if it's a boolean using the objCType
-            let objCType = String(cString: number.objCType)
-            if objCType == "c" || objCType == "B" { // These represent BOOLs in ObjC
-                return .boolean(number.boolValue)
-            } else {
-                return .number(number.doubleValue)
-            }
-        case let bool as Bool:
-            return .boolean(bool)
-        case let array as [Any]:
-            return .array(array.map(convertToJSONValue))
-        case let dict as [String: Any]:
-            return .object(dict.mapValues(convertToJSONValue))
-        case is NSNull:
-            return .null
-        default:
-            return .null
-        }
-    }
-
-    private static func valuesAreEqual(
-        _ value1: JSONValue,
-        _ value2: JSONValue,
-        approximately: Double?,
-        approximateKeys: [String: Double],
-        flexibleArrayKeys: [String],
-        propertiesToSkip: Set<String>,
-        currentPath: String
-    ) -> Bool {
-        switch (value1, value2) {
-        case (.null, .null):
-            return true
-        case let (.string(s1), .string(s2)):
-            return s1 == s2
-        case let (.string(s1), .number(n2)):
-            guard let n1 = Double(s1) else { return false }
-            return n1.isApproximatelyEqual(to: n2, epsilon: approximately)
-        case let (.number(n1), .string(s2)):
-            guard let n2 = Double(s2) else { return false }
-            return n1.isApproximatelyEqual(to: n2, epsilon: approximately)
-        case let (.number(n1), .number(n2)):
-            let match = n1.isApproximatelyEqual(to: n2, epsilon: approximately)
-            return match
-        case let (.boolean(b1), .boolean(b2)):
-            return b1 == b2
-        case let (.array(a1), .array(a2)):
-            if flexibleArrayKeys.contains(currentPath), !a1.isEmpty, !a2.isEmpty {
-                let shortestCount = min(a1.count, a2.count)
-                return zip(a1.prefix(shortestCount), a2.prefix(shortestCount)).allSatisfy { v1, v2 in
-                    valuesAreEqual(
-                        v1, v2, approximately: approximately, approximateKeys: approximateKeys,
-                        flexibleArrayKeys: flexibleArrayKeys, propertiesToSkip: propertiesToSkip,
-                        currentPath: currentPath
-                    )
-                }
-            }
-            return a1.count == a2.count && zip(a1, a2).allSatisfy { v1, v2 in
-                valuesAreEqual(
-                    v1, v2, approximately: approximately, approximateKeys: approximateKeys,
-                    flexibleArrayKeys: flexibleArrayKeys, propertiesToSkip: propertiesToSkip,
-                    currentPath: currentPath
-                )
-            }
-        case let (.object(o1), .object(o2)):
-            // Filter out properties that should be skipped during comparison
-            let keys1 = Set(o1.keys).subtracting(propertiesToSkip)
-            let keys2 = Set(o2.keys).subtracting(propertiesToSkip)
-            return keys1 == keys2 && keys1.allSatisfy { key in
-                guard let v1 = o1[key], let v2 = o2[key] else { return false }
-                return valuesAreEqual(
-                    v1, v2, approximately: approximateKeys[key], approximateKeys: approximateKeys,
-                    flexibleArrayKeys: flexibleArrayKeys, propertiesToSkip: propertiesToSkip,
-                    currentPath: "\(currentPath).\(key)"
-                )
-            }
-        default:
-            return false
-        }
-    }
-}

+ 0 - 167
Trio/Sources/APS/OpenAPSSwift/Logging/OrefFunction.swift

@@ -1,167 +0,0 @@
-import Foundation
-
-/// After the port from Javascript to Swift is complete, we should remove the logging module:
-/// https://github.com/nightscout/Trio-dev/issues/293
-
-enum OrefFunctionResult {
-    case success(RawJSON)
-    case failure(Error)
-
-    func returnOrThrow() throws -> RawJSON {
-        switch self {
-        case let .success(json): return json
-        case let .failure(error): throw error
-        }
-    }
-}
-
-enum OrefFunction: String, Codable {
-    enum ReturnType {
-        case array
-        case dictionary
-    }
-
-    case autosens
-    case iob
-    case meal
-    case makeProfile
-    case determineBasal
-
-    // since we're removing some keys from our Profile that exist in Javascript
-    // we need to let the difference function know which keys to ignore when
-    // calculating differences
-    func keysToIgnore() -> Set<String> {
-        switch self {
-        case .makeProfile:
-            return Set(["calc_glucose_noise", "enableEnliteBgproxy", "exercise_mode", "offline_hotspot"])
-        case .iob:
-            return Set()
-        case .meal:
-            // These aren't used by downstream calculations, so we
-            // can ignore them in our comparison
-            // However, slopeFromMaxDeviation and slopeFromMinDeviation
-            // are used but we had to include them here because small
-            // changes in iob.activity can lead to large changes in these
-            // values in rare cases
-            return Set([
-                "maxDeviation",
-                "minDeviation",
-                "allDeviations",
-                "bwCarbs",
-                "bwFound",
-                "journalCarbs",
-                "nsCarbs",
-                "slopeFromMaxDeviation",
-                "slopeFromMinDeviation"
-            ])
-        case .autosens:
-            return Set(["deviationsUnsorted", "debugInfo"])
-        case .determineBasal:
-            // We ignore some properties that aren't used downstream
-            return Set([
-                // Not used, ignore
-                "id",
-                "temp",
-                "reservoir",
-                "ISF",
-                "TDD",
-                "minDelta",
-                "received",
-                "deliverAt",
-                // intentionally removed from Swift, but in JS
-                "insulinForManualBolus",
-                "manualBolusErrorString",
-                // in JS but not in Swift
-                "tick",
-                "BGI",
-                "target_bg",
-                "deviation",
-                // in Swift but not in JS
-                "timestamp",
-                "minGuardBG",
-                "minPredBG"
-            ])
-        }
-    }
-
-    // Some values might be slightly different due to Double vs Decimal
-    // and minor algorithmic differences
-    func approximateMatchingNumbers() -> [String: Double] {
-        switch self {
-        case .makeProfile:
-            return [:]
-        case .iob:
-            // for iob we can get rounding errors because of Double vs Decimal
-            // so we leave a little extra room for our comparisons
-            return [
-                "iob": 0.1,
-                "activity": 0.01,
-                "basaliob": 0.25,
-                "bolusiob": 0.25,
-                "netbasalinsulin": 0.25,
-                "bolusinsulin": 0.25
-            ]
-        case .meal:
-            return [
-                "carbs": 0.1,
-                "mealCOB": 10,
-                "currentDeviation": 1,
-                "lastCarbTime": 1
-            ]
-        case .autosens:
-            return [
-                "ratio": 0.021,
-                "newisf": 3.1
-            ]
-        case .determineBasal:
-            return [
-                "sensitivityRatio": 0.011,
-                "expectedDelta": 0.11,
-                "eventualBG": 1.1,
-                "IOB": 1.1,
-                "ZT": 1.1,
-                "UAM": 1.1,
-                "COB": 1.1
-            ]
-        }
-    }
-
-    func returnType() -> ReturnType {
-        switch self {
-        case .makeProfile:
-            return .dictionary
-        case .iob:
-            return .array
-        case .meal:
-            return .dictionary
-        case .autosens:
-            return .dictionary
-        case .determineBasal:
-            return .dictionary
-        }
-    }
-
-    func flexibleArrayKeys() -> [String] {
-        switch self {
-        case .determineBasal:
-            return ["predBGs.UAM", "predBGs.COB", "predBGs.ZT", "predBGs.IOB"]
-        default:
-            return []
-        }
-    }
-
-    /// Properties to skip during object comparison. Unlike keysToIgnore which filters
-    /// final differences, this skips properties during the recursive comparison itself.
-    /// This is needed for array return types where differences are recorded at the
-    /// element level rather than at individual property paths.
-    func propertiesToSkip() -> Set<String> {
-        switch self {
-        case .iob:
-            // Please see this issue for context on skipping lastTemp:
-            // https://github.com/nightscout/Trio-dev/issues/453
-            return Set(["lastTemp"])
-        default:
-            return Set()
-        }
-    }
-}

+ 13 - 0
Trio/Sources/APS/OpenAPSSwift/OrefFunctionResult.swift

@@ -0,0 +1,13 @@
+import Foundation
+
+enum OrefFunctionResult {
+    case success(RawJSON)
+    case failure(Error)
+
+    func returnOrThrow() throws -> RawJSON {
+        switch self {
+        case let .success(json): return json
+        case let .failure(error): throw error
+        }
+    }
+}

+ 0 - 363
TrioTests/OpenAPSSwiftTests/AutosensJsonTests.swift

@@ -1,363 +0,0 @@
-import Foundation
-import Testing
-@testable import Trio
-
-@Suite("Autosens using real JSON", .serialized) struct AutosensJsonTests {
-    let timeZoneForTests = TimeZoneForTests()
-
-    func checkFixedJsAgainstSwift(autosensInputs: AutosensInputs) async throws {
-        let openAps = OpenAPSFixed()
-        let autosensResultSwift = OpenAPSSwift.autosense(
-            glucose: autosensInputs.glucose,
-            pumpHistory: autosensInputs.history,
-            basalProfile: autosensInputs.basalProfile,
-            profile: try JSONBridge.to(autosensInputs.profile),
-            carbs: autosensInputs.carbs,
-            tempTargets: autosensInputs.tempTargets,
-            clock: autosensInputs.clock,
-            includeDeviationsForTesting: true
-        )
-
-        let autosensResultJavascript = await openAps.autosenseJavascript(
-            glucose: autosensInputs.glucose,
-            pumpHistory: autosensInputs.history,
-            basalprofile: autosensInputs.basalProfile,
-            profile: try JSONBridge.to(autosensInputs.profile),
-            carbs: autosensInputs.carbs,
-            temptargets: autosensInputs.tempTargets,
-            clock: autosensInputs.clock,
-            prepareFile: OpenAPSFixed.prepare
-        )
-
-        let comparison = JSONCompare.createComparison(
-            function: .autosens,
-            swift: autosensResultSwift,
-            swiftDuration: 0.1,
-            javascript: autosensResultJavascript,
-            javascriptDuration: 0.1,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        if comparison.resultType == .valueDifference {
-            print(comparison.differences!.prettyPrintedJSON!)
-        }
-
-        if comparison.resultType != .matching {
-            print("REPLAY ERROR: Fixed JS didn't match")
-        }
-
-        #expect(comparison.resultType == .matching)
-    }
-
-    func compareDeviations(swiftJson: String, jsJson: String) throws {
-        // Parse both JSON strings
-        let swiftData = swiftJson.data(using: .utf8)!
-        let jsData = jsJson.data(using: .utf8)!
-
-        let swiftDict = try JSONSerialization.jsonObject(with: swiftData) as! [String: Any]
-        let jsDict = try JSONSerialization.jsonObject(with: jsData) as! [String: Any]
-
-        // Extract debug info
-        let swiftDebugInfo = swiftDict["debugInfo"] as! [Any]
-        let jsDebugInfo = jsDict["debugInfo"] as! [Any]
-
-        // Extract deviationsUnsorted arrays
-        let swiftDeviations = swiftDict["deviationsUnsorted"] as! [Any]
-        let jsDeviations = jsDict["deviationsUnsorted"] as! [Any]
-
-        let combined: [String: Any] = [
-            "swiftDebugInfo": swiftDebugInfo,
-            "jsDebugInfo": jsDebugInfo,
-            "swiftDeviations": swiftDeviations,
-            "jsDeviations": jsDeviations
-        ]
-        let sharedDir = FileManager.default.temporaryDirectory
-        let outputURL = sharedDir.appendingPathComponent("autosens_debug.json")
-        let jsonData = try JSONSerialization.data(withJSONObject: combined, options: .prettyPrinted)
-        try jsonData.write(to: outputURL)
-        print("Writing debug info to: \(outputURL.path)")
-
-        // Convert both to Double arrays
-        let swiftDoubles = swiftDeviations.compactMap { value -> Double? in
-            if let number = value as? NSNumber {
-                return number.doubleValue
-            }
-            return nil
-        }
-
-        let jsDoubles = jsDeviations.compactMap { value -> Double? in
-            if let number = value as? NSNumber {
-                return number.doubleValue
-            } else if let string = value as? String {
-                return Double(string)
-            }
-            return nil
-        }
-
-        // Compare the arrays
-        print("Swift array count: \(swiftDoubles.count)")
-        print("JS array count: \(jsDoubles.count)")
-
-        guard swiftDoubles.count == jsDoubles.count else {
-            print("Arrays have different lengths!")
-            let count = max(swiftDoubles.count, jsDoubles.count)
-            var index = 0
-            while index < count {
-                let swiftDouble = index < swiftDoubles.count ? String(swiftDoubles[index]) : "nil"
-                let jsDouble = index < jsDoubles.count ? String(jsDoubles[index]) : "nil"
-                print("Index: \(index), Swift: \(swiftDouble), JS: \(jsDouble)")
-                index += 1
-            }
-            return
-        }
-
-        var differences: [(index: Int, swift: Double, js: Double)] = []
-
-        for (index, (swiftVal, jsVal)) in zip(swiftDoubles, jsDoubles).enumerated() {
-            if abs(swiftVal - jsVal) > 0.001 { // Small tolerance for floating point comparison
-                differences.append((index: index, swift: swiftVal, js: jsVal))
-            }
-        }
-
-        if differences.isEmpty {
-            print("✅ Arrays are identical (within tolerance)")
-        } else {
-            print("❌ Found \(differences.count) differences:")
-            for diff in differences {
-                print("  Index \(diff.index): Swift=\(diff.swift), JS=\(diff.js)")
-            }
-        }
-    }
-
-    @Test(
-        "should produce same results for autosens for fixed JS",
-        .enabled(if: ReplayTests.enabled)
-    ) func replayErrorInputs() async throws {
-        let timezone = ReplayTests.timezone
-        let files = try await HttpFiles.listFiles()
-        for filePath in files {
-            let algorithmComparison = try await HttpFiles.downloadFile(at: filePath)
-            print("Checking \(filePath) @ \(algorithmComparison.createdAt)")
-            guard timezone == algorithmComparison.timezone else {
-                continue
-            }
-            guard let autosensInputs = algorithmComparison.autosensInput else {
-                print("Skipping, no autosensInputs found")
-                if let str = algorithmComparison.comparisonError {
-                    print(str)
-                }
-                if let str = algorithmComparison.swiftException {
-                    print(str)
-                }
-                continue
-            }
-
-            if IobJsonTests.pumpIsSuspended(history: autosensInputs.history) {
-                print("Skipping, known issue with JS and currently suspended pumps")
-                continue
-            }
-
-            timeZoneForTests.setTimezone(identifier: algorithmComparison.timezone)
-
-            try await checkFixedJsAgainstSwift(autosensInputs: autosensInputs)
-            print("Checked \(filePath) @ \(algorithmComparison.createdAt)")
-
-            timeZoneForTests.resetTimezone()
-        }
-    }
-
-    @Test("Compare IoB calculation at specific time", .enabled(if: false)) func compareIobAtTime() async throws {
-        // Hard-code the file and time to investigate
-        let filePath = "/files/9e146319-5160-482e-9135-f461b97f1a9f.0.json"
-        let targetClock = Date("2025-09-08T10:42:44.333Z")!
-
-        let algorithmComparison = try await HttpFiles.downloadFile(at: filePath)
-        guard let autosensInputs = algorithmComparison.autosensInput else {
-            print("No autosensInputs found")
-            return
-        }
-
-        timeZoneForTests.setTimezone(identifier: algorithmComparison.timezone)
-
-        let profile = autosensInputs.profile
-
-        // Prepare treatments the same way AutosensGenerator does
-        let swiftTreatments = try IobHistory.calcTempTreatments(
-            history: autosensInputs.history.map { $0.computedEvent() },
-            profile: profile,
-            clock: autosensInputs.clock,
-            autosens: nil,
-            zeroTempDuration: nil
-        )
-
-        let encoder = JSONCoding.encoder
-        var output = try encoder.encode(swiftTreatments)
-
-        let sharedDir = FileManager.default.temporaryDirectory
-        var outputURL = sharedDir.appendingPathComponent("swift_treatments.json")
-        try output.write(to: outputURL)
-
-        print("Writing \(outputURL.path)")
-
-        // Set up profile with currentBasal for this time (both Swift and JS autosens do this)
-        var simulationProfile = profile
-        simulationProfile.currentBasal = try Basal.basalLookup(autosensInputs.basalProfile, now: targetClock)
-        simulationProfile.temptargetSet = false
-
-        // Calculate Swift IoB at this time
-        let swiftIob = try IobCalculation.iobTotal(
-            treatments: swiftTreatments,
-            profile: simulationProfile,
-            time: targetClock
-        )
-
-        let openAps = OpenAPSFixed()
-        let jsTreatmentsRaw = try await openAps.iobHistory(
-            pumphistory: autosensInputs.history,
-            profile: try JSONBridge.to(autosensInputs.profile),
-            clock: autosensInputs.clock,
-            autosens: RawJSON.null,
-            zeroTempDuration: RawJSON.null
-        )
-
-        let jsTreatments = try JSONDecoder()
-            .decode([IobJsonTests.IobHistoryResult].self, from: jsTreatmentsRaw.rawJSON.data(using: .utf8)!)
-
-        output = try encoder.encode(jsTreatments)
-        outputURL = sharedDir.appendingPathComponent("js_treatments.json")
-        try output.write(to: outputURL)
-
-        print("Writing \(outputURL.path)")
-
-        print("Swift IoB at \(targetClock):")
-        print("  iob: \(swiftIob.iob)")
-        print("  activity: \(swiftIob.activity)")
-
-        timeZoneForTests.resetTimezone()
-    }
-
-    @Test("Format autosens inputs for running in JS", .enabled(if: false)) func formatInputs() async throws {
-        // this test is meant for one-off analysis so it's ok to hard code
-        // a file, just make sure to _not_ check in updates to this to
-        // avoid polluting our change logs
-        let algorithmComparison = try await HttpFiles.downloadFile(at: "/files/2084152d-a95e-4d0e-9254-e0951f7aa519.0.json")
-        let autosensInputs = algorithmComparison.autosensInput!
-
-        let encoder = JSONCoding.encoder
-        let output = try encoder.encode(autosensInputs)
-
-        let sharedDir = FileManager.default.temporaryDirectory
-        let outputURL = sharedDir.appendingPathComponent("autosens_error_inputs.json")
-        try output.write(to: outputURL)
-
-        // Print the path so you can find it
-        print("Writing to: \(outputURL.path)")
-
-        timeZoneForTests.setTimezone(identifier: algorithmComparison.timezone)
-
-        let openAps = OpenAPSFixed()
-        let autosensResultSwift = OpenAPSSwift.autosense(
-            glucose: autosensInputs.glucose,
-            pumpHistory: autosensInputs.history,
-            basalProfile: autosensInputs.basalProfile,
-            profile: try JSONBridge.to(autosensInputs.profile),
-            carbs: autosensInputs.carbs,
-            tempTargets: autosensInputs.tempTargets,
-            clock: autosensInputs.clock,
-            includeDeviationsForTesting: true
-        )
-
-        let autosensResultJavascript = await openAps.autosenseJavascript(
-            glucose: autosensInputs.glucose,
-            pumpHistory: autosensInputs.history,
-            basalprofile: autosensInputs.basalProfile,
-            profile: try JSONBridge.to(autosensInputs.profile),
-            carbs: autosensInputs.carbs,
-            temptargets: autosensInputs.tempTargets,
-            clock: autosensInputs.clock,
-            prepareFile: OpenAPSFixed.prepare
-        )
-
-        if case let .success(swiftJson) = autosensResultSwift, case let .success(jsJson) = autosensResultJavascript {
-            try compareDeviations(swiftJson: swiftJson, jsJson: jsJson)
-        }
-
-        try await checkFixedJsAgainstSwift(autosensInputs: autosensInputs)
-
-        timeZoneForTests.resetTimezone()
-    }
-
-    @Test(
-        "Format autosens inputs for running in JS, 24 hours only",
-        .enabled(if: false)
-    ) func formatInputsFixedTime() async throws {
-        // this test is meant for one-off analysis so it's ok to hard code
-        // a file, just make sure to _not_ check in updates to this to
-        // avoid polluting our change logs
-        let algorithmComparison = try await HttpFiles.downloadFile(at: "/files/2084152d-a95e-4d0e-9254-e0951f7aa519.0.json")
-        let autosensInputs = algorithmComparison.autosensInput!
-
-        // change these variables to switch between 24 and 8 hours
-        // 288 for 24 hours, 96 for 8 hours
-        let maxDeviations = 288
-        // OpenAPSFixed.prepare24 and OpenAPSFixed.prepare8
-        let prepareFile = OpenAPSFixed.prepare24
-
-        let encoder = JSONCoding.encoder
-        let output = try encoder.encode(autosensInputs)
-
-        let sharedDir = FileManager.default.temporaryDirectory
-        let outputURL = sharedDir.appendingPathComponent("autosens_error_inputs.json")
-        try output.write(to: outputURL)
-
-        // Print the path so you can find it
-        print("Writing to: \(outputURL.path)")
-
-        timeZoneForTests.setTimezone(identifier: algorithmComparison.timezone)
-
-        let openAps = OpenAPSFixed()
-
-        let glucose = try JSONBridge.glucose(from: autosensInputs.glucose)
-        let pumpHistory = try JSONBridge.pumpHistory(from: autosensInputs.history)
-        let basalProfile = try JSONBridge.basalProfile(from: autosensInputs.basalProfile)
-        let profile = autosensInputs.profile
-        let carbs = try JSONBridge.carbs(from: autosensInputs.carbs)
-        let tempTargets = try JSONBridge.tempTargets(from: autosensInputs.tempTargets)
-        let clock = autosensInputs.clock
-
-        let autosensResultSwift = try AutosensGenerator.generate(
-            glucose: glucose,
-            pumpHistory: pumpHistory,
-            basalProfile: basalProfile,
-            profile: profile,
-            carbs: carbs,
-            tempTargets: tempTargets,
-            maxDeviations: maxDeviations,
-            clock: clock,
-            includeDeviationsForTesting: true
-        )
-
-        let autosensResultJavascript = await openAps.autosenseJavascript(
-            glucose: autosensInputs.glucose,
-            pumpHistory: autosensInputs.history,
-            basalprofile: autosensInputs.basalProfile,
-            profile: try JSONBridge.to(autosensInputs.profile),
-            carbs: autosensInputs.carbs,
-            temptargets: autosensInputs.tempTargets,
-            clock: autosensInputs.clock,
-            prepareFile: prepareFile
-        )
-
-        if case let .success(jsJson) = autosensResultJavascript {
-            try compareDeviations(swiftJson: JSONBridge.to(autosensResultSwift), jsJson: jsJson)
-        }
-
-        try await checkFixedJsAgainstSwift(autosensInputs: autosensInputs)
-
-        timeZoneForTests.resetTimezone()
-    }
-}

+ 0 - 252
TrioTests/OpenAPSSwiftTests/DetermineBasalJsonTests.swift

@@ -1,252 +0,0 @@
-import Foundation
-import Testing
-@testable import Trio
-
-@Suite("DetermineBasal testing using JSON inputs", .serialized) struct DetermineBasalJsonTests {
-    let timeZoneForTests = TimeZoneForTests()
-
-    @Test(
-        "DetermineBasal should produce same results for fixed JS",
-        .enabled(if: ReplayTests.enabled)
-    ) func replayErrorInputs() async throws {
-        // Note: This test case can only test one timezone per invocation
-        // so you need to manually change this to try out errors from
-        // different timezones
-        let testingTimezone = ReplayTests.timezone
-        let files = try await HttpFiles.listFiles()
-        for filePath in files {
-            let algorithmComparison = try await HttpFiles.downloadFile(at: filePath)
-            print("Checking \(filePath) @ \(algorithmComparison.createdAt)")
-            guard algorithmComparison.timezone == testingTimezone else {
-                continue
-            }
-            guard let determineBasalInput = algorithmComparison.determineBasalInput else {
-                print("Skipping, no determineBasalInput found")
-                if let str = algorithmComparison.comparisonError {
-                    print(str)
-                }
-                if let str = algorithmComparison.swiftException {
-                    print(str)
-                }
-                continue
-            }
-
-            timeZoneForTests.setTimezone(identifier: algorithmComparison.timezone)
-
-            try await checkFixedJsAgainstSwift(determineBasalInput: determineBasalInput)
-            print("Checked \(filePath) \(algorithmComparison.timezone)")
-            timeZoneForTests.resetTimezone()
-        }
-    }
-
-    func checkFixedJsAgainstSwift(determineBasalInput: DetermineBasalInputs) async throws {
-        let openAps = OpenAPSFixed()
-        let determineBasalResultSwift = OpenAPSSwift.determineBasal(
-            glucose: determineBasalInput.glucose,
-            currentTemp: determineBasalInput.currentTemp,
-            iob: try JSONBridge.to(determineBasalInput.iob),
-            profile: try JSONBridge.to(determineBasalInput.profile),
-            autosens: try JSONBridge.to(determineBasalInput.autosens),
-            meal: try JSONBridge.to(determineBasalInput.meal),
-            microBolusAllowed: determineBasalInput.microBolusAllowed,
-            reservoir: determineBasalInput.reservoir ?? 0,
-            pumpHistory: determineBasalInput.pumpHistory,
-            preferences: determineBasalInput.preferences,
-            basalProfile: determineBasalInput.basalProfile,
-            trioCustomOrefVariables: determineBasalInput.trioCustomOrefVariables,
-            clock: determineBasalInput.clock
-        )
-
-        let determineBasalResultJavascript = try await openAps.determineBasalJavascript(
-            glucose: determineBasalInput.glucose,
-            currentTemp: determineBasalInput.currentTemp,
-            iob: try JSONBridge.to(determineBasalInput.iob),
-            profile: try JSONBridge.to(determineBasalInput.profile),
-            autosens: try JSONBridge.to(determineBasalInput.autosens),
-            meal: try JSONBridge.to(determineBasalInput.meal),
-            microBolusAllowed: determineBasalInput.microBolusAllowed,
-            reservoir: determineBasalInput.reservoir ?? 0,
-            pumpHistory: determineBasalInput.pumpHistory,
-            preferences: determineBasalInput.preferences,
-            basalProfile: determineBasalInput.basalProfile,
-            trioCustomOrefVariables: determineBasalInput.trioCustomOrefVariables,
-            clock: determineBasalInput.clock
-        )
-
-        let comparison = JSONCompare.createComparison(
-            function: .determineBasal,
-            swift: determineBasalResultSwift,
-            swiftDuration: 0.1,
-            javascript: determineBasalResultJavascript,
-            javascriptDuration: 0.1,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        if comparison.resultType == .valueDifference {
-            print(comparison.differences!.prettyPrintedJSON!)
-        }
-
-        if comparison.resultType != .matching {
-            print("REPLAY ERROR: Fixed JS didn't match")
-        }
-
-        #expect(comparison.resultType == .matching)
-    }
-
-    @Test("Format determineBasal inputs for running in JS", .enabled(if: false)) func formatInputs() async throws {
-        let openAps = OpenAPSFixed()
-
-        // this test is meant for one-off analysis so it's ok to hard code
-        // a file, just make sure to _not_ check in updates to this to
-        // avoid polluting our change logs
-        let algorithmComparison = try await HttpFiles.downloadFile(at: "/files/f1d04efa-c39b-4f0a-9955-65ab663ff9fb.0.json")
-        let determineBasalInput = algorithmComparison.determineBasalInput!
-
-        let encoder = JSONCoding.encoder
-        let output = try encoder.encode(determineBasalInput)
-
-        let sharedDir = FileManager.default.temporaryDirectory
-        let outputURL = sharedDir.appendingPathComponent("determine_basal_error_inputs.json")
-        // Print the path so you can find it
-        print("Writing to: \(outputURL.path)")
-        try output.write(to: outputURL)
-
-        timeZoneForTests.setTimezone(identifier: algorithmComparison.timezone)
-
-        let determineBasalResultSwift = OpenAPSSwift.determineBasal(
-            glucose: determineBasalInput.glucose,
-            currentTemp: determineBasalInput.currentTemp,
-            iob: try JSONBridge.to(determineBasalInput.iob),
-            profile: try JSONBridge.to(determineBasalInput.profile),
-            autosens: try JSONBridge.to(determineBasalInput.autosens),
-            meal: try JSONBridge.to(determineBasalInput.meal),
-            microBolusAllowed: determineBasalInput.microBolusAllowed,
-            reservoir: determineBasalInput.reservoir ?? 0,
-            pumpHistory: determineBasalInput.pumpHistory,
-            preferences: determineBasalInput.preferences,
-            basalProfile: determineBasalInput.basalProfile,
-            trioCustomOrefVariables: determineBasalInput.trioCustomOrefVariables,
-            clock: determineBasalInput.clock
-        )
-
-        print("Swift result")
-        switch determineBasalResultSwift {
-        case let .success(rawJson):
-            print(rawJson)
-        case let .failure(error):
-            print(error.localizedDescription)
-        }
-
-        let determineBasalResultJavascript = try await openAps.determineBasalJavascript(
-            glucose: determineBasalInput.glucose,
-            currentTemp: determineBasalInput.currentTemp,
-            iob: try JSONBridge.to(determineBasalInput.iob),
-            profile: try JSONBridge.to(determineBasalInput.profile),
-            autosens: try JSONBridge.to(determineBasalInput.autosens),
-            meal: try JSONBridge.to(determineBasalInput.meal),
-            microBolusAllowed: determineBasalInput.microBolusAllowed,
-            reservoir: determineBasalInput.reservoir ?? 0,
-            pumpHistory: determineBasalInput.pumpHistory,
-            preferences: determineBasalInput.preferences,
-            basalProfile: determineBasalInput.basalProfile,
-            trioCustomOrefVariables: determineBasalInput.trioCustomOrefVariables,
-            clock: determineBasalInput.clock
-        )
-
-        print("Fixed JS result")
-        switch determineBasalResultJavascript {
-        case let .success(rawJson):
-            print(rawJson)
-        case let .failure(error):
-            print(error.localizedDescription)
-        }
-
-        let comparison = JSONCompare.createComparison(
-            function: .determineBasal,
-            swift: determineBasalResultSwift,
-            swiftDuration: 0.1,
-            javascript: determineBasalResultJavascript,
-            javascriptDuration: 0.1,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        if comparison.resultType == .valueDifference {
-            print(comparison.differences!.prettyPrintedJSON!)
-            printForecasts(comparison.differences)
-        }
-
-        #expect(comparison.resultType == .matching)
-
-        timeZoneForTests.resetTimezone()
-    }
-
-    func printForecasts(_ values: [String: Any]?) {
-        guard let values = values else { return }
-        guard let forecasts = values["predBGs"] as? Trio.ValueDifference else { return }
-        let js = forecasts.js.toDictionary()
-        let swift = forecasts.swift.toDictionary()
-
-        for forecastType in ["IOB", "ZT", "UAM", "COB"] {
-            print("")
-            guard let swiftForecast = swift[forecastType]?.toIntArray(),
-                  let jsForecast = js[forecastType]?.toIntArray()
-            else {
-                print("missing \(forecastType) forecast, skipping")
-                continue
-            }
-            if swiftForecast.count == jsForecast.count {
-                print(forecastType)
-            } else {
-                print("\(forecastType) has length mismatch ❌")
-            }
-            print("Row\tSft\tJS\tMatch")
-            print("--------------")
-            for (row, values) in zip(swiftForecast, jsForecast).enumerated() {
-                let pass: String
-                if abs(values.0 - values.1) <= 1 {
-                    pass = "✅"
-                } else {
-                    pass = "❌"
-                }
-                print("\(row)\t\(values.0)\t\(values.1)\t\(pass)")
-            }
-        }
-    }
-}
-
-extension JSONValue {
-    func toDictionary() -> [String: Trio.JSONValue] {
-        switch self {
-        case let .object(dict):
-            return dict
-        default:
-            fatalError()
-        }
-    }
-
-    func toIntArray() -> [Int] {
-        switch self {
-        case let .array(array):
-            return array.map { $0.toInt() }
-        default:
-            fatalError()
-        }
-    }
-
-    func toInt() -> Int {
-        switch self {
-        case let .number(number):
-            return Int(number)
-        default:
-            fatalError()
-        }
-    }
-}

+ 0 - 284
TrioTests/OpenAPSSwiftTests/IobJsonTests.swift

@@ -1,284 +0,0 @@
-import Foundation
-import Testing
-@testable import Trio
-
-/// This test suite is to help us debug and verify iob errors from Trio devices
-///
-/// There are two key components. First, we have a version of the Javascript that has a number
-/// of bugs fixed. We don't want to fix the real Javascript, so we put this fixed Javascript in the
-/// testing bundle and use it to run comparisons. If the error we see in the field is one that we know
-/// about and have fixed in JS, the Swift and JS implementations will produce the same results. You
-/// can find the fixed JS here:
-///  https://github.com/kingst/trio-oref/tree/tcd-fixes-for-swift-comparison
-///
-/// Second, we have a server that runs (part of `trio-oref-logs`) to serve error logs captured
-/// from the field. This server needs to run on the same machine as the simulator where this test runs.
-/// You can find more information about it from the `trio-oref-logs` repo.
-@Suite("IoB using real pump history JSON", .serialized) struct IobJsonTests {
-    let timeZoneForTests = TimeZoneForTests()
-
-    struct IobHistoryResult: Codable {
-        var insulin: Decimal?
-        var rate: Decimal?
-        var duration: Decimal?
-        var timestamp: String?
-        var started_at: String?
-        var created_at: String?
-        var date: Decimal?
-
-        enum CodingKeys: String, CodingKey {
-            case insulin
-            case rate
-            case duration
-            case timestamp
-            case started_at
-            case created_at
-            case date
-        }
-    }
-
-    static func pumpIsSuspended(history: [PumpHistoryEvent]) -> Bool {
-        // The JS implementation of IoB when the pump is suspend is so fundamentally
-        // broken that I wasn't able to fix it in JS. So we'll just skip these, but I
-        // verified them by hand and the Swift implementation appears to be correct
-        if let mostRecentSuspendResumeEvent = history.filter({ $0.type == .pumpSuspend || $0.type == .pumpResume })
-            .first
-        {
-            return mostRecentSuspendResumeEvent.type == .pumpSuspend
-        }
-        return false
-    }
-
-    // Note: This test case has a memory leak so limit your inputs
-    // to about 250 files at a time
-    @Test(
-        "IoB should produce same results for fixed JS and different for bundle JS",
-        .enabled(if: ReplayTests.enabled)
-    ) func replayErrorInputs() async throws {
-        let files = try await HttpFiles.listFiles()
-        let testingTimezone = ReplayTests.timezone
-        for filePath in files {
-            let algorithmComparison = try await HttpFiles.downloadFile(at: filePath)
-            print("Checking \(filePath) @ \(algorithmComparison.createdAt)")
-            guard algorithmComparison.timezone == testingTimezone else {
-                continue
-            }
-            guard let iobInputs = algorithmComparison.iobInput else {
-                print("Skipping, no iobInputs found")
-                if let str = algorithmComparison.comparisonError {
-                    print(str)
-                }
-                if let str = algorithmComparison.swiftException {
-                    print(str)
-                }
-                continue
-            }
-
-            if IobJsonTests.pumpIsSuspended(history: iobInputs.history) {
-                print("Skipping, known issue with JS and currently suspended pumps")
-                continue
-            }
-
-            timeZoneForTests.setTimezone(identifier: algorithmComparison.timezone)
-
-            try await checkFixedJsAgainstSwift(iobInputs: iobInputs)
-            // try await checkBundleJsAgainstSwift(iobInputs: iobInputs)
-
-            timeZoneForTests.resetTimezone()
-        }
-    }
-
-    func checkFixedJsAgainstSwift(iobInputs: IobInputs) async throws {
-        let openAps = OpenAPSFixed()
-        let iobResultSwift = OpenAPSSwift.iob(
-            pumphistory: iobInputs.history,
-            profile: try JSONBridge.to(iobInputs.profile),
-            clock: iobInputs.clock,
-            autosens: try JSONBridge.to(iobInputs.autosens)
-        )
-
-        let iobResultJavascript = await openAps.iobJavascript(
-            pumphistory: iobInputs.history,
-            profile: try JSONBridge.to(iobInputs.profile),
-            clock: iobInputs.clock,
-            autosens: try JSONBridge.to(iobInputs.autosens)
-        )
-
-        // In suspendedPrior mode (first suspend/resume event is a Resume), JS incorrectly
-        // returns pre-resume temp basals in lastTemp because history.js line 566 uses
-        // tempHistory instead of splitHistory. Swift correctly handles this case.
-        if case let .success(jsRawJson) = iobResultJavascript,
-           let jsIobEntries = try? JSONBridge.iobResult(from: jsRawJson),
-           let jsLastTempDate = jsIobEntries.first?.lastTemp?.date
-        {
-            let suspendResumeEvents = iobInputs.history
-                .filter { $0.type == .pumpSuspend || $0.type == .pumpResume }
-                .sorted { $0.timestamp < $1.timestamp }
-            if let firstEvent = suspendResumeEvents.first,
-               firstEvent.type == .pumpResume
-            {
-                let firstResumeTime = UInt64(firstEvent.timestamp.timeIntervalSince1970 * 1000)
-                if jsLastTempDate < firstResumeTime {
-                    print("Skipping, known issue with JS lastTemp in suspendedPrior mode")
-                    return
-                }
-            }
-        }
-
-        let comparison = JSONCompare.createComparison(
-            function: .iob,
-            swift: iobResultSwift,
-            swiftDuration: 0.1,
-            javascript: iobResultJavascript,
-            javascriptDuration: 0.1,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        if comparison.resultType == .valueDifference {
-            print(comparison.differences!.prettyPrintedJSON!)
-        }
-
-        if comparison.resultType != .matching {
-            print("REPLAY ERROR: Fixed JS didn't match")
-        }
-
-        #expect(comparison.resultType == .matching)
-    }
-
-    func checkBundleJsAgainstSwift(iobInputs: IobInputs) async throws {
-        let openAps = OpenAPS(storage: BaseFileStorage(), tddStorage: MockTDDStorage())
-        let iobResultSwift = OpenAPSSwift.iob(
-            pumphistory: iobInputs.history,
-            profile: try JSONBridge.to(iobInputs.profile),
-            clock: iobInputs.clock,
-            autosens: try JSONBridge.to(iobInputs.autosens)
-        )
-
-        let iobResultJavascript = await openAps.iobJavascript(
-            pumphistory: iobInputs.history,
-            profile: try JSONBridge.to(iobInputs.profile),
-            clock: iobInputs.clock,
-            autosens: try JSONBridge.to(iobInputs.autosens)
-        )
-
-        let comparison = JSONCompare.createComparison(
-            function: .iob,
-            swift: iobResultSwift,
-            swiftDuration: 0.1,
-            javascript: iobResultJavascript,
-            javascriptDuration: 0.1,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        if comparison.resultType != .valueDifference {
-            print("REPLAY ERROR: bundle JS did't produce value difference")
-        }
-
-        #expect(comparison.resultType == .valueDifference)
-    }
-
-    func checkHistoryConsistency(swiftTreatments: [ComputedPumpHistoryEvent], jsTreatments: [IobHistoryResult]) {
-        let swiftNetBolus = swiftTreatments.compactMap(\.insulin).filter({ $0 >= 0.1 }).reduce(0, +)
-        let jsNetBolus = jsTreatments.compactMap(\.insulin).filter({ $0 >= 0.1 }).reduce(0, +)
-
-        let swiftNetBasal = swiftTreatments.compactMap(\.insulin).filter({ $0 < 0.1 }).reduce(0, +)
-        let jsNetBasal = jsTreatments.compactMap(\.insulin).filter({ $0 < 0.1 }).reduce(0, +)
-
-        #expect(swiftNetBasal == jsNetBasal)
-        #expect(swiftNetBolus == jsNetBolus)
-    }
-
-    func checkRunningBasal(swiftTreatments: [ComputedPumpHistoryEvent], jsTreatments: [IobHistoryResult]) {
-        let swiftBasals = swiftTreatments.filter({ $0.rate != nil }).filter({ $0.duration! > 0 })
-        let jsBasals = jsTreatments.filter({ $0.rate != nil }).filter({ $0.duration! > 0 })
-
-        #expect(swiftBasals.count == jsBasals.count)
-        for (swift, js) in zip(swiftBasals, jsBasals) {
-            #expect(Decimal(swift.date) == js.date!)
-            #expect(swift.duration!.isWithin(0.01, of: js.duration!))
-            #expect(swift.rate == js.rate)
-
-            let start = js.date!
-            let end = js.date! + js.duration! * 60 * 1000
-            let swiftTempBolus = swiftTreatments
-                .filter({ Decimal($0.date) >= start && Decimal($0.date) < end && $0.insulin != nil && $0.insulin! < 0.1 })
-                .map({ $0.insulin! }).reduce(0, +)
-            let jsTempBolus = jsTreatments
-                .filter({ $0.date! >= start && $0.date! < end && $0.insulin != nil && $0.insulin! < 0.1 }).map({ $0.insulin! })
-                .reduce(0, +)
-
-            if swiftTempBolus != jsTempBolus {
-                print("temp bolus @ \(swift.timestamp) mismatch swift: \(swiftTempBolus) js: \(jsTempBolus)")
-            }
-            #expect(swiftTempBolus == jsTempBolus)
-        }
-    }
-
-    @Test("Debug utility for checking one IOB error", .enabled(if: false)) func debugSignleIobError() async throws {
-        let algorithmComparison = try await HttpFiles.downloadFile(at: "/files/dd31e618-5023-40ca-ab7e-0fdd2475fbd9.2.json")
-        let iobInputs = algorithmComparison.iobInput!
-
-        timeZoneForTests.setTimezone(identifier: algorithmComparison.timezone)
-
-        try await checkFixedJsAgainstSwift(iobInputs: iobInputs)
-
-        timeZoneForTests.resetTimezone()
-    }
-
-    @Test("Debug utility for checking iob-history", .enabled(if: false)) func debugIobHistory() async throws {
-        let algorithmComparison = try await HttpFiles.downloadFile(at: "/files/dd31e618-5023-40ca-ab7e-0fdd2475fbd9.2.json")
-        let iobInputs = algorithmComparison.iobInput!
-
-        timeZoneForTests.setTimezone(identifier: algorithmComparison.timezone)
-
-        let swiftIobHistory = try IobHistory.calcTempTreatments(
-            history: iobInputs.history.map { $0.computedEvent() },
-            profile: iobInputs.profile,
-            clock: iobInputs.clock,
-            autosens: iobInputs.autosens,
-            zeroTempDuration: nil
-        )
-
-        let openAps = OpenAPSFixed()
-        let jsIobHistoryRaw = try await openAps.iobHistory(
-            pumphistory: iobInputs.history,
-            profile: JSONBridge.to(iobInputs.profile),
-            clock: iobInputs.clock,
-            autosens: JSONBridge.to(iobInputs.autosens),
-            zeroTempDuration: RawJSON.null
-        )
-        let jsIobHistory = try JSONDecoder().decode([IobHistoryResult].self, from: jsIobHistoryRaw.rawJSON.data(using: .utf8)!)
-
-        let encoder = JSONCoding.encoder
-        var output = try encoder.encode(swiftIobHistory)
-        var sharedDir = FileManager.default.temporaryDirectory
-        var outputURL = sharedDir.appendingPathComponent("swift_treatments.json")
-        print("Writing to: \(outputURL.path)")
-        try output.write(to: outputURL)
-
-        output = try encoder.encode(jsIobHistory)
-        sharedDir = FileManager.default.temporaryDirectory
-        outputURL = sharedDir.appendingPathComponent("js_treatments.json")
-        print("Writing to: \(outputURL.path)")
-        try output.write(to: outputURL)
-
-        output = try encoder.encode(iobInputs)
-        sharedDir = FileManager.default.temporaryDirectory
-        outputURL = sharedDir.appendingPathComponent("js_iob_input_error.json")
-        print("Writing to: \(outputURL.path)")
-        try output.write(to: outputURL)
-
-        checkHistoryConsistency(swiftTreatments: swiftIobHistory, jsTreatments: jsIobHistory)
-        checkRunningBasal(swiftTreatments: swiftIobHistory, jsTreatments: jsIobHistory)
-
-        timeZoneForTests.resetTimezone()
-    }
-}

+ 0 - 214
TrioTests/OpenAPSSwiftTests/JSONCompareTests.swift

@@ -1,214 +0,0 @@
-import Foundation
-import Testing
-@testable import Trio
-
-@Suite("JSON Compare") struct JSONCompareTests {
-    // Test fixtures
-    let matchingJSON = """
-    {
-        "value": 42,
-        "text": "hello",
-        "flag": true,
-        "nested": {
-            "array": [1, 2, 3],
-            "object": {"key": "value"}
-        }
-    }
-    """
-
-    @Test("should find no differences between identical JSONs") func matchingJSONs() async throws {
-        let differences = try JSONCompare.differences(
-            function: .makeProfile,
-            swift: matchingJSON,
-            javascript: matchingJSON
-        )
-        #expect(differences.isEmpty)
-    }
-
-    @Test("should detect scalar value differences") func scalarDifferences() async throws {
-        let jsJSON = """
-        {
-            "number": 42,
-            "text": "hello",
-            "boolean": true
-        }
-        """
-
-        let swiftJSON = """
-        {
-            "number": 43,
-            "text": "world",
-            "boolean": false
-        }
-        """
-
-        let differences = try JSONCompare.differences(
-            function: .makeProfile,
-            swift: swiftJSON,
-            javascript: jsJSON
-        )
-
-        #expect(differences.count == 3)
-        #expect(differences["number"]?.js == .number(42))
-        #expect(differences["number"]?.swift == .number(43))
-        #expect(differences["text"]?.js == .string("hello"))
-        #expect(differences["text"]?.swift == .string("world"))
-        #expect(differences["boolean"]?.js == .boolean(true))
-        #expect(differences["boolean"]?.swift == .boolean(false))
-    }
-
-    @Test("should detect missing keys") func missingKeys() async throws {
-        let jsJSON = """
-        {
-            "common": 42,
-            "jsOnly": "hello"
-        }
-        """
-
-        let swiftJSON = """
-        {
-            "common": 42,
-            "swiftOnly": "world"
-        }
-        """
-
-        let differences = try JSONCompare.differences(
-            function: .makeProfile,
-            swift: swiftJSON,
-            javascript: jsJSON
-        )
-
-        #expect(differences.count == 2)
-        #expect(differences["jsOnly"]?.nativeKeyMissing == true)
-        #expect(differences["jsOnly"]?.jsKeyMissing == false)
-        #expect(differences["swiftOnly"]?.jsKeyMissing == true)
-        #expect(differences["swiftOnly"]?.nativeKeyMissing == false)
-    }
-
-    @Test("should detect nested object differences") func nestedDifferences() async throws {
-        let jsJSON = """
-        {
-            "nested": {
-                "value": 42,
-                "array": [1, 2, 3]
-            }
-        }
-        """
-
-        let swiftJSON = """
-        {
-            "nested": {
-                "value": 43,
-                "array": [1, 2, 4]
-            }
-        }
-        """
-
-        let differences = try JSONCompare.differences(
-            function: .makeProfile,
-            swift: swiftJSON,
-            javascript: jsJSON
-        )
-
-        #expect(differences.count == 1)
-        guard case let .object(nestedDiff) = differences["nested"]?.js else {
-            throw TestFailure("Expected nested object difference")
-        }
-        #expect(nestedDiff["value"] == .number(42))
-        #expect(nestedDiff["array"] == .array([.number(1), .number(2), .number(3)]))
-    }
-
-    @Test("should ignore specified keys for makeProfile") func keyIgnoring() async throws {
-        let jsJSON = """
-        {
-            "value": 42,
-            "calc_glucose_noise": true,
-            "enableEnliteBgproxy": false
-        }
-        """
-
-        let swiftJSON = """
-        {
-            "value": 42
-        }
-        """
-
-        let differences = try JSONCompare.differences(
-            function: .makeProfile,
-            swift: swiftJSON,
-            javascript: jsJSON
-        )
-        #expect(differences.isEmpty)
-    }
-
-    @Test("should handle invalid JSON") func invalidJSON() async throws {
-        let invalidJSON = "{ invalid json }"
-
-        do {
-            _ = try JSONCompare.differences(
-                function: .makeProfile,
-                swift: invalidJSON,
-                javascript: matchingJSON
-            )
-            throw TestFailure("Expected error for invalid JSON")
-        } catch {
-            // Expected error
-            #expect(true)
-        }
-    }
-
-    @Test("should handle empty JSON objects") func emptyObjects() async throws {
-        let emptyJSON = "{}"
-        let differences = try JSONCompare.differences(
-            function: .makeProfile,
-            swift: emptyJSON,
-            javascript: emptyJSON
-        )
-        #expect(differences.isEmpty)
-    }
-
-    @Test("should detect array length differences") func arrayLengthDifferences() async throws {
-        let jsJSON = """
-        {
-            "array": [1, 2, 3]
-        }
-        """
-
-        let swiftJSON = """
-        {
-            "array": [1, 2]
-        }
-        """
-
-        let differences = try JSONCompare.differences(
-            function: .makeProfile,
-            swift: swiftJSON,
-            javascript: jsJSON
-        )
-
-        #expect(differences.count == 1)
-        guard case let .array(jsArray) = differences["array"]?.js,
-              case let .array(swiftArray) = differences["array"]?.swift
-        else {
-            throw TestFailure("Expected array differences")
-        }
-        #expect(jsArray.count == 3)
-        #expect(swiftArray.count == 2)
-    }
-
-    @Test("should be empty array for {} and [] pump history strings") func emptyPumpHistoryParsing() async throws {
-        let emptyArray = try JSONBridge.pumpHistory(from: "[]")
-        let emptyObject = try JSONBridge.pumpHistory(from: "{}")
-
-        #expect(emptyArray.isEmpty)
-        #expect(emptyObject.isEmpty)
-    }
-}
-
-struct TestFailure: Error {
-    let message: String
-
-    init(_ message: String) {
-        self.message = message
-    }
-}

+ 0 - 167
TrioTests/OpenAPSSwiftTests/MealJsonTests.swift

@@ -1,167 +0,0 @@
-import Foundation
-import Testing
-@testable import Trio
-
-@Suite("Meal testing using JSON inputs", .serialized) struct MealJsonTests {
-    let timeZoneForTests = TimeZoneForTests()
-
-    @Test(
-        "Meal should produce same results for fixed JS",
-        .enabled(if: ReplayTests.enabled)
-    ) func replayErrorInputs() async throws {
-        // Note: This test case can only test one timezone per invocation
-        // so you need to manually change this to try out errors from
-        // different timezones
-        let testingTimezone = ReplayTests.timezone
-        let files = try await HttpFiles.listFiles()
-        for filePath in files {
-            let algorithmComparison = try await HttpFiles.downloadFile(at: filePath)
-            print("Checking \(filePath) @ \(algorithmComparison.createdAt)")
-            guard algorithmComparison.timezone == testingTimezone else {
-                continue
-            }
-            guard let mealInputs = algorithmComparison.mealInput else {
-                print("Skipping, no mealInputs found")
-                if let str = algorithmComparison.comparisonError {
-                    print(str)
-                }
-                if let str = algorithmComparison.swiftException {
-                    print(str)
-                }
-                continue
-            }
-
-            // The JS implementation of IoB when the pump is suspend is so fundamentally
-            // broken that I wasn't able to fix it in JS. So we'll just skip these, but I
-            // verified them by hand and the Swift implementation appears to be correct
-            if let mostRecentPumpEvent = mealInputs.pumpHistory.filter({ $0.isExternal != true }).first {
-                if mostRecentPumpEvent.type == .pumpSuspend
-                {
-                    print("Skipping, known issue with JS and currently suspended pumps")
-                    continue
-                }
-            }
-
-            timeZoneForTests.setTimezone(identifier: algorithmComparison.timezone)
-            try await checkFixedJsAgainstSwift(mealInputs: mealInputs)
-            print("Checked \(filePath) \(algorithmComparison.timezone)")
-            timeZoneForTests.resetTimezone()
-        }
-    }
-
-    func checkFixedJsAgainstSwift(mealInputs: MealInputs) async throws {
-        let openAps = OpenAPSFixed()
-        let mealResultSwift = OpenAPSSwift.meal(
-            pumphistory: mealInputs.pumpHistory,
-            profile: try JSONBridge.to(mealInputs.profile),
-            basalProfile: mealInputs.basalProfile,
-            clock: mealInputs.clock,
-            carbs: mealInputs.carbs,
-            glucose: mealInputs.glucose
-        )
-
-        let mealResultJavascript = await openAps.mealJavascript(
-            pumphistory: mealInputs.pumpHistory,
-            profile: try JSONBridge.to(mealInputs.profile),
-            basalProfile: mealInputs.basalProfile,
-            clock: mealInputs.clock,
-            carbs: mealInputs.carbs,
-            glucose: mealInputs.glucose
-        )
-
-        let comparison = JSONCompare.createComparison(
-            function: .meal,
-            swift: mealResultSwift,
-            swiftDuration: 0.1,
-            javascript: mealResultJavascript,
-            javascriptDuration: 0.1,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        if comparison.resultType == .valueDifference {
-            print(comparison.differences!.prettyPrintedJSON!)
-        }
-
-        if comparison.resultType != .matching {
-            print("REPLAY ERROR: Fixed JS didn't match")
-        }
-
-        #expect(comparison.resultType == .matching)
-    }
-
-    @Test("Format meal inputs for running in JS", .enabled(if: false)) func formatInputs() async throws {
-        let openAps = OpenAPSFixed()
-
-        // this test is meant for one-off analysis so it's ok to hard code
-        // a file, just make sure to _not_ check in updates to this to
-        // avoid polluting our change logs
-        let algorithmComparison = try await HttpFiles.downloadFile(at: "/files/7a8a377e-f483-46a5-adbb-290baa04801b.3.json")
-        let mealInputs = algorithmComparison.mealInput!
-
-        let encoder = JSONCoding.encoder
-        let output = try encoder.encode(mealInputs)
-
-        let sharedDir = FileManager.default.temporaryDirectory
-        let outputURL = sharedDir.appendingPathComponent("meal_error_inputs.json")
-        // Print the path so you can find it
-        print("Writing to: \(outputURL.path)")
-        try output.write(to: outputURL)
-
-        timeZoneForTests.setTimezone(identifier: algorithmComparison.timezone)
-
-        let mealResultSwift = OpenAPSSwift.meal(
-            pumphistory: mealInputs.pumpHistory,
-            profile: try JSONBridge.to(mealInputs.profile),
-            basalProfile: mealInputs.basalProfile,
-            clock: mealInputs.clock,
-            carbs: mealInputs.carbs,
-            glucose: mealInputs.glucose
-        )
-
-        print("Swift result")
-        switch mealResultSwift {
-        case let .success(rawJson):
-            print(rawJson)
-        case let .failure(error):
-            print(error.localizedDescription)
-        }
-
-        let mealResultJavascript = await openAps.mealJavascript(
-            pumphistory: mealInputs.pumpHistory,
-            profile: try JSONBridge.to(mealInputs.profile),
-            basalProfile: mealInputs.basalProfile,
-            clock: mealInputs.clock,
-            carbs: mealInputs.carbs,
-            glucose: mealInputs.glucose
-        )
-
-        print("Fixed JS result")
-        switch mealResultJavascript {
-        case let .success(rawJson):
-            print(rawJson)
-        case let .failure(error):
-            print(error.localizedDescription)
-        }
-
-        let comparison = JSONCompare.createComparison(
-            function: .meal,
-            swift: mealResultSwift,
-            swiftDuration: 0.1,
-            javascript: mealResultJavascript,
-            javascriptDuration: 0.1,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        #expect(comparison.resultType == .matching)
-
-        timeZoneForTests.resetTimezone()
-    }
-}

+ 0 - 66
TrioTests/OpenAPSSwiftTests/ProfileJavascriptTests.swift

@@ -275,70 +275,4 @@ struct ProfileGeneratorTests {
 
         #expect(profile.model == "554")
     }
-
-//    @Test("Profile should use temptargetSet key in output json") func testTempTargetSetKey() async throws {
-//        var inputs = createBaseInputs()
-//        inputs.7 = "\"554\"\n"
-//        let now = Date()
-//        let tempTargets = [
-//            TempTarget(
-//                name: nil,
-//                createdAt: now - 1.hoursToSeconds,
-//                targetTop: 100,
-//                targetBottom: 80,
-//                duration: 120,
-//                enteredBy: nil,
-//                reason: nil,
-//                isPreset: nil,
-//                enabled: nil,
-//                halfBasalTarget: nil
-//            )
-//        ]
-//
-//        let openAps = OpenAPS(storage: BaseFileStorage(), tddStorage: MockTDDStorage())
-//        let jsResult = await openAps.makeProfileJavascript(
-//            preferences: inputs.4,
-//            pumpSettings: inputs.0,
-//            bgTargets: inputs.1,
-//            basalProfile: inputs.2,
-//            isf: inputs.3,
-//            carbRatio: inputs.5,
-//            tempTargets: tempTargets,
-//            model: inputs.7,
-//            autotune: RawJSON.null,
-//            trioSettings: inputs.8
-//        )
-//
-//        let (swiftResult, makeProfileInputs) = OpenAPSSwift.makeProfile(
-//            preferences: inputs.4,
-//            pumpSettings: inputs.0,
-//            bgTargets: inputs.1,
-//            basalProfile: inputs.2,
-//            isf: inputs.3,
-//            carbRatio: inputs.5,
-//            tempTargets: tempTargets,
-//            model: inputs.7,
-//            trioSettings: inputs.8,
-//            clock: now
-//        )
-//
-//        let comparison = JSONCompare.createComparison(
-//            function: .makeProfile,
-//            swift: swiftResult,
-//            swiftDuration: 1.0,
-//            javascript: jsResult,
-//            javascriptDuration: 1.0,
-//            iobInputs: nil,
-//            mealInputs: nil,
-//            autosensInputs: nil,
-//            determineBasalInputs: nil,
-//            makeProfileInputs: makeProfileInputs
-//        )
-//
-//        if comparison.resultType == .valueDifference {
-//            print(comparison.differences!.prettyPrintedJSON!)
-//        }
-//
-//        #expect(comparison.resultType == .matching)
-//    }
 }

+ 0 - 265
TrioTests/OpenAPSSwiftTests/ProfileJsNativeCompareTests.swift

@@ -1,265 +0,0 @@
-import Foundation
-import Testing
-@testable import Trio
-
-@Suite("Profile js vs native comparison") struct ProfileJsNativeCompareTests {
-    // Base test inputs that match the JavaScript test setup
-    private func createBaseInputs() -> (
-        Preferences,
-        PumpSettings,
-        BGTargets,
-        [BasalProfileEntry],
-        InsulinSensitivities,
-        CarbRatios,
-        [TempTarget],
-        String,
-        TrioSettings
-    ) {
-        let pumpSettings = PumpSettings(
-            insulinActionCurve: 10,
-            maxBolus: 10,
-            maxBasal: 2
-        )
-
-        let bgTargets = BGTargets(
-            units: .mgdL,
-            userPreferredUnits: .mgdL,
-            targets: [
-                BGTargetEntry(low: 100, high: 120, start: "00:00", offset: 0)
-            ]
-        )
-
-        let basalProfile = [
-            BasalProfileEntry(start: "00:00", minutes: 0, rate: 1.0)
-        ]
-
-        let isf = InsulinSensitivities(
-            units: .mgdL,
-            userPreferredUnits: .mgdL,
-            sensitivities: [
-                InsulinSensitivityEntry(sensitivity: 100, offset: 0, start: "00:00")
-            ]
-        )
-
-        var preferences = Preferences()
-
-        // Modify preferences to make sure that modified properties
-        // propogate to Profile
-        preferences.smbDeliveryRatio = 0.4
-
-        let carbRatios = CarbRatios(
-            units: .grams,
-            schedule: [
-                CarbRatioEntry(start: "00:00", offset: 0, ratio: 20)
-            ]
-        )
-
-        let tempTargets: [TempTarget] = []
-        let model = "\"250\""
-        let trioSettings = TrioSettings()
-
-        return (preferences, pumpSettings, bgTargets, basalProfile, isf, carbRatios, tempTargets, model, trioSettings)
-    }
-
-    @Test("should compare Profile for js and native with base inputs") func withBasicInputs() async throws {
-        let inputs = createBaseInputs()
-        let openAps = OpenAPS(storage: BaseFileStorage(), tddStorage: MockTDDStorage())
-        let profileJs = await openAps.makeProfileJavascript(
-            preferences: inputs.0,
-            pumpSettings: inputs.1,
-            bgTargets: inputs.2,
-            basalProfile: inputs.3,
-            isf: inputs.4,
-            carbRatio: inputs.5,
-            tempTargets: inputs.6,
-            model: inputs.7,
-            autotune: RawJSON.null,
-            trioSettings: inputs.8
-        )
-
-        let profileSwift = OpenAPSSwift.makeProfile(
-            preferences: inputs.0,
-            pumpSettings: inputs.1,
-            bgTargets: inputs.2,
-            basalProfile: inputs.3,
-            isf: inputs.4,
-            carbRatio: inputs.5,
-            tempTargets: inputs.6,
-            model: inputs.7,
-            trioSettings: inputs.8,
-            clock: Date()
-        )
-
-        let comparison = JSONCompare.createComparison(
-            function: .makeProfile,
-            swift: profileSwift,
-            swiftDuration: 0.1,
-            javascript: profileJs,
-            javascriptDuration: 0.1,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        #expect(comparison.resultType == .matching)
-    }
-}
-
-@Suite("Algorithm Comparison Creation") struct ComparisonCreationTests {
-    // Test fixtures
-    let matchingJSON = """
-    {
-        "value": 42
-    }
-    """
-
-    let differentJSON = """
-    {
-        "value": 43
-    }
-    """
-
-    let invalidJSON = "{ invalid json"
-
-    @Test("should create matching comparison when values are identical") func matchingValues() async throws {
-        let comparison = JSONCompare.createComparison(
-            function: .makeProfile,
-            swift: .success(matchingJSON),
-            swiftDuration: 0.1,
-            javascript: .success(matchingJSON),
-            javascriptDuration: 0.2,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        #expect(comparison.resultType == .matching)
-        #expect(comparison.differences == nil)
-        #expect(comparison.jsDuration == 0.2)
-        #expect(comparison.swiftDuration == 0.1)
-        #expect(comparison.jsException == nil)
-        #expect(comparison.swiftException == nil)
-        #expect(comparison.comparisonError == nil)
-    }
-
-    @Test("should detect value differences") func valueDifferences() async throws {
-        let comparison = JSONCompare.createComparison(
-            function: .makeProfile,
-            swift: .success(differentJSON),
-            swiftDuration: 0.1,
-            javascript: .success(matchingJSON),
-            javascriptDuration: 0.2,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        #expect(comparison.resultType == .valueDifference)
-        #expect(comparison.differences != nil)
-        #expect(comparison.differences?["value"] != nil)
-        #expect(comparison.jsDuration == 0.2)
-        #expect(comparison.swiftDuration == 0.1)
-        #expect(comparison.jsException == nil)
-        #expect(comparison.swiftException == nil)
-        #expect(comparison.comparisonError == nil)
-    }
-
-    @Test("should handle matching exceptions") func matchingExceptions() async throws {
-        let error = NSError(domain: "test", code: 1, userInfo: nil)
-        let comparison = JSONCompare.createComparison(
-            function: .makeProfile,
-            swift: .failure(error),
-            swiftDuration: 0.1,
-            javascript: .failure(error),
-            javascriptDuration: 0.2,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        #expect(comparison.resultType == .matchingExceptions)
-        #expect(comparison.differences == nil)
-        #expect(comparison.jsException != nil)
-        #expect(comparison.swiftException != nil)
-        #expect(comparison.comparisonError == nil)
-    }
-
-    @Test("should handle Swift-only exceptions") func swiftOnlyException() async throws {
-        let error = NSError(domain: "test", code: 1, userInfo: nil)
-        let comparison = JSONCompare.createComparison(
-            function: .makeProfile,
-            swift: .failure(error),
-            swiftDuration: 0.1,
-            javascript: .success(matchingJSON),
-            javascriptDuration: 0.2,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        #expect(comparison.resultType == .swiftOnlyException)
-        #expect(comparison.differences == nil)
-        #expect(comparison.jsException == nil)
-        #expect(comparison.swiftException != nil)
-        #expect(comparison.jsDuration == 0.2)
-        #expect(comparison.swiftDuration == nil)
-        #expect(comparison.comparisonError == nil)
-    }
-
-    @Test("should handle JavaScript-only exceptions") func javascriptOnlyException() async throws {
-        let error = NSError(domain: "test", code: 1, userInfo: nil)
-        let comparison = JSONCompare.createComparison(
-            function: .makeProfile,
-            swift: .success(matchingJSON),
-            swiftDuration: 0.1,
-            javascript: .failure(error),
-            javascriptDuration: 0.2,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        #expect(comparison.resultType == .jsOnlyException)
-        #expect(comparison.differences == nil)
-        #expect(comparison.jsException != nil)
-        #expect(comparison.swiftException == nil)
-        #expect(comparison.jsDuration == nil)
-        #expect(comparison.swiftDuration == 0.1)
-        #expect(comparison.comparisonError == nil)
-    }
-
-    @Test("should handle comparison errors with invalid JSON") func comparisonError() async throws {
-        let comparison = JSONCompare.createComparison(
-            function: .makeProfile,
-            swift: .success(invalidJSON),
-            swiftDuration: 0.1,
-            javascript: .success(matchingJSON),
-            javascriptDuration: 0.2,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        #expect(comparison.resultType == .comparisonError)
-        #expect(comparison.differences == nil)
-        #expect(comparison.jsException == nil)
-        #expect(comparison.swiftException == nil)
-        #expect(comparison.comparisonError != nil)
-        #expect(comparison.jsDuration == 0.2)
-        #expect(comparison.swiftDuration == 0.1)
-    }
-}

+ 0 - 93
TrioTests/OpenAPSSwiftTests/ProfileJsonTests.swift

@@ -1,93 +0,0 @@
-import Foundation
-import Testing
-@testable import Trio
-
-@Suite("Profile testing using JSON inputs", .serialized) struct ProfileJsonTests {
-    let timeZoneForTests = TimeZoneForTests()
-
-    @Test(
-        "Profile should produce same results for fixed JS",
-        .enabled(if: ReplayTests.enabled)
-    ) func replayErrorInputs() async throws {
-        // Note: This test case can only test one timezone per invocation
-        // so you need to manually change this to try out errors from
-        // different timezones
-        let testingTimezone = ReplayTests.timezone
-        let files = try await HttpFiles.listFiles()
-        for filePath in files {
-            let algorithmComparison = try await HttpFiles.downloadFile(at: filePath)
-            print("Checking \(filePath) @ \(algorithmComparison.createdAt)")
-            guard algorithmComparison.timezone == testingTimezone else {
-                continue
-            }
-            guard let profileInputs = algorithmComparison.makeProfileInput else {
-                print("Skipping, no profileInputs found")
-                if let str = algorithmComparison.comparisonError {
-                    print(str)
-                }
-                if let str = algorithmComparison.swiftException {
-                    print(str)
-                }
-                continue
-            }
-
-            timeZoneForTests.setTimezone(identifier: algorithmComparison.timezone)
-            try await checkFixedJsAgainstSwift(profileInputs: profileInputs)
-            print("Checked \(filePath) \(algorithmComparison.timezone)")
-            timeZoneForTests.resetTimezone()
-        }
-    }
-
-    func checkFixedJsAgainstSwift(profileInputs: MakeProfileInputs) async throws {
-        let openAps = OpenAPSFixed()
-        let profileResultSwift = OpenAPSSwift.makeProfile(
-            preferences: profileInputs.preferences,
-            pumpSettings: profileInputs.pumpSettings,
-            bgTargets: profileInputs.bgTargets,
-            basalProfile: profileInputs.basalProfile,
-            isf: profileInputs.isf,
-            carbRatio: profileInputs.carbRatios,
-            tempTargets: profileInputs.tempTargets,
-            model: profileInputs.model,
-            trioSettings: profileInputs.trioSettings,
-            clock: profileInputs.clock
-        )
-
-        let profileResultJavascript = await openAps.makeProfileJavascript(
-            preferences: profileInputs.preferences,
-            pumpSettings: profileInputs.pumpSettings,
-            bgTargets: profileInputs.bgTargets,
-            basalProfile: profileInputs.basalProfile,
-            isf: profileInputs.isf,
-            carbRatio: profileInputs.carbRatios,
-            tempTargets: profileInputs.tempTargets,
-            model: profileInputs.model,
-            autotune: RawJSON.null,
-            trioSettings: profileInputs.trioSettings,
-            clock: profileInputs.clock
-        )
-
-        let comparison = JSONCompare.createComparison(
-            function: .makeProfile,
-            swift: profileResultSwift,
-            swiftDuration: 0.1,
-            javascript: profileResultJavascript,
-            javascriptDuration: 0.1,
-            iobInputs: nil,
-            mealInputs: nil,
-            autosensInputs: nil,
-            determineBasalInputs: nil,
-            makeProfileInputs: nil
-        )
-
-        if comparison.resultType == .valueDifference {
-            print(comparison.differences!.prettyPrintedJSON!)
-        }
-
-        if comparison.resultType != .matching {
-            print("REPLAY ERROR: Fixed JS didn't match")
-        }
-
-        #expect(comparison.resultType == .matching)
-    }
-}

+ 0 - 32
TrioTests/OpenAPSSwiftTests/javascript/bundle/autosens-prepare-24.js

@@ -1,32 +0,0 @@
-// для settings/autosens.json параметры: monitor/glucose.json monitor/pumphistory-24h-zoned.json settings/basal_profile.json settings/profile.json monitor/carbhistory.json settings/temptargets.json
-
-function generate(glucose_data, pumphistory_data, basalprofile, profile_data, carb_data = {}, temptarget_data = {}, now = null) {
-    if (glucose_data.length < 72) {
-        return { "ratio": 1, "error": "not enough glucose data to calculate autosens" };
-    };
-    
-    if (now) {
-        now = new Date(now);
-    } else {
-        now = new Date();
-    }
-    
-    var iob_inputs = {
-        history: pumphistory_data,
-        profile: profile_data,
-        clock: now
-    };
-
-    var detection_inputs = {
-        iob_inputs: iob_inputs,
-        carbs: carb_data,
-        glucose_data: glucose_data,
-        basalprofile: basalprofile,
-        temptargets: temptarget_data
-    };
-    
-    // 24 hours only
-    detection_inputs.deviations = 288;
-    return trio_autosens(detection_inputs, now);
-}
-

+ 0 - 32
TrioTests/OpenAPSSwiftTests/javascript/bundle/autosens-prepare-8.js

@@ -1,32 +0,0 @@
-// для settings/autosens.json параметры: monitor/glucose.json monitor/pumphistory-24h-zoned.json settings/basal_profile.json settings/profile.json monitor/carbhistory.json settings/temptargets.json
-
-function generate(glucose_data, pumphistory_data, basalprofile, profile_data, carb_data = {}, temptarget_data = {}, now = null) {
-    if (glucose_data.length < 72) {
-        return { "ratio": 1, "error": "not enough glucose data to calculate autosens" };
-    };
-    
-    if (now) {
-        now = new Date(now);
-    } else {
-        now = new Date();
-    }
-    
-    var iob_inputs = {
-        history: pumphistory_data,
-        profile: profile_data,
-        clock: now
-    };
-
-    var detection_inputs = {
-        iob_inputs: iob_inputs,
-        carbs: carb_data,
-        glucose_data: glucose_data,
-        basalprofile: basalprofile,
-        temptargets: temptarget_data
-    };
-    
-    // 8 hours only
-    detection_inputs.deviations = 96;
-    return trio_autosens(detection_inputs, now);
-}
-

+ 0 - 33
TrioTests/OpenAPSSwiftTests/javascript/bundle/autosens-prepare.js

@@ -1,33 +0,0 @@
-// для settings/autosens.json параметры: monitor/glucose.json monitor/pumphistory-24h-zoned.json settings/basal_profile.json settings/profile.json monitor/carbhistory.json settings/temptargets.json
-
-function generate(glucose_data, pumphistory_data, basalprofile, profile_data, carb_data = {}, temptarget_data = {}, now = null) {
-    if (glucose_data.length < 72) {
-        return { "ratio": 1, "error": "not enough glucose data to calculate autosens" };
-    };
-    
-    if (now) {
-        now = new Date(now);
-    } else {
-        now = new Date();
-    }
-    
-    var iob_inputs = {
-        history: pumphistory_data,
-        profile: profile_data,
-        clock: now
-    };
-
-    var detection_inputs = {
-        iob_inputs: iob_inputs,
-        carbs: carb_data,
-        glucose_data: glucose_data,
-        basalprofile: basalprofile,
-        temptargets: temptarget_data
-    };
-    detection_inputs.deviations = 96;
-    var ratio8h = trio_autosens(detection_inputs, now);
-    detection_inputs.deviations = 288;
-    var ratio24h = trio_autosens(detection_inputs, now);
-    var lowestRatio = ratio8h.ratio < ratio24h.ratio ? ratio8h : ratio24h;
-    return lowestRatio;
-}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 2
TrioTests/OpenAPSSwiftTests/javascript/bundle/autosens.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 1
TrioTests/OpenAPSSwiftTests/javascript/bundle/autotune-core.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 2
TrioTests/OpenAPSSwiftTests/javascript/bundle/autotune-prep.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 1
TrioTests/OpenAPSSwiftTests/javascript/bundle/basal-set-temp.js


+ 0 - 51
TrioTests/OpenAPSSwiftTests/javascript/bundle/determine-basal-prepare.js

@@ -1,51 +0,0 @@
-//для enact/smb-suggested.json параметры: monitor/iob.json monitor/temp_basal.json monitor/glucose.json settings/profile.json settings/autosens.json --meal monitor/meal.json --microbolus --reservoir monitor/reservoir.json
-
-function generate(iob, currenttemp, glucose, profile, autosens = null, meal = null, microbolusAllowed = false, reservoir = null, clock = new Date(), pump_history, preferences, basalProfile, trio_custom_oref_variables) {
-
-    // We pass in the clock when we're replaying
-    //var clock = new Date();
-    
-    var middleware_was_used = "";
-    try {
-        var middlewareReason = middleware(iob, currenttemp, glucose, profile, autosens, meal, reservoir, clock, pump_history, preferences, basalProfile, trio_custom_oref_variables);
-        middleware_was_used = (middlewareReason || "Nothing changed");
-        console.log("Middleware reason: " + middleware_was_used);
-    } catch (error) {
-        console.log("Invalid middleware: " + error);
-    };
-
-    var glucose_status = trio_glucoseGetLast(glucose);
-    var autosens_data = null;
-
-    if (autosens) {
-        autosens_data = autosens;
-    }
-    
-    var reservoir_data = null;
-    if (reservoir) {
-        reservoir_data = reservoir;
-    }
-
-    var meal_data = {};
-    if (meal) {
-        meal_data = meal;
-    }
-    
-    var pumphistory = {};
-    if (pump_history) {
-        pumphistory = pump_history;
-    }
-    
-    var basalprofile = {};
-    if (basalProfile) {
-        basalprofile = basalProfile;
-    }
-    
-    var trio_custom_oref_variables_temp = {};
-    if (trio_custom_oref_variables) {
-        trio_custom_oref_variables_temp = trio_custom_oref_variables;
-    }
-    
-    return trio_determineBasal(glucose_status, currenttemp, iob, profile, autosens_data, meal_data, trio_basalSetTemp, microbolusAllowed, reservoir_data, clock, pumphistory, preferences, basalprofile, trio_custom_oref_variables_temp, middleware_was_used);
-}
-

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 1
TrioTests/OpenAPSSwiftTests/javascript/bundle/determine-basal.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 1
TrioTests/OpenAPSSwiftTests/javascript/bundle/glucose-get-last.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 1
TrioTests/OpenAPSSwiftTests/javascript/bundle/iob-calculate.js


+ 0 - 13
TrioTests/OpenAPSSwiftTests/javascript/bundle/iob-history-prepare.js

@@ -1,13 +0,0 @@
-function generate(pumphistory_data, profile_data, clock_data, autosens_data, zeroTempDuration) {
-    var inputs = {
-        history: pumphistory_data
-        , profile: profile_data
-        , clock: clock_data
-    };
-
-    if (autosens_data) {
-        inputs.autosens = autosens_data;
-    }
-    
-    return trio_iobHistory.calcTempTreatments(inputs, zeroTempDuration);
-}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 2
TrioTests/OpenAPSSwiftTests/javascript/bundle/iob-history.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 1
TrioTests/OpenAPSSwiftTests/javascript/bundle/iob-total.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 2
TrioTests/OpenAPSSwiftTests/javascript/bundle/iob.js


+ 0 - 51
TrioTests/OpenAPSSwiftTests/javascript/bundle/meal-prepare.js

@@ -1,51 +0,0 @@
-//для monitor/meal.json параметры: monitor/pumphistory-24h-zoned.json settings/profile.json monitor/clock-zoned.json monitor/glucose.json settings/basal_profile.json monitor/carbhistory.json
-
-function generate(pumphistory_data, profile_data, clock_data, glucose_data, basalprofile_data, carbhistory = false) {
-    if (typeof(profile_data.carb_ratio) === 'undefined' || profile_data.carb_ratio < 0.1) {
-        return {"error":"Error: carb_ratio " + profile_data.carb_ratio + " out of bounds"};
-    }
-
-    var carb_data = { };
-    if (carbhistory) {
-        carb_data = carbhistory;
-    }
-
-    if (typeof basalprofile_data[0] === 'undefined') {
-        return { "error":"Error: bad basalprofile_data: " + JSON.stringify(basalprofile_data) };
-    }
-
-    var inputs = {
-      history: pumphistory_data
-    , profile: profile_data
-    , basalprofile: basalprofile_data
-    , clock: clock_data
-    , carbs: carb_data
-    , glucose: glucose_data
-    };
-
-    var recentCarbs = trio_meal(inputs);
-
-    if (glucose_data.length < 4) {
-        console.error("Not enough glucose data to calculate carb absorption; found:", glucose_data.length);
-        
-        // We're returning a sensable default to match Swift
-        /*
-        recentCarbs.mealCOB = 0;
-        recentCarbs.reason = "not enough glucose data to calculate carb absorption";
-         */
-        return {
-            carbs: 0,
-            mealCOB: 0,
-            currentDeviation: 0,
-            maxDeviation: 0,
-            minDeviation: 0,
-            slopeFromMaxDeviation: 0,
-            slopeFromMinDeviation: 0,
-            allDeviations: [],
-            lastCarbTime: 0
-        };
-    }
-
-    return recentCarbs;
-}
-

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 2
TrioTests/OpenAPSSwiftTests/javascript/bundle/meal.js


+ 0 - 113
TrioTests/OpenAPSSwiftTests/javascript/bundle/profile-prepare.js

@@ -1,113 +0,0 @@
-//для pumpprofile.json параметры: settings/settings.json settings/bg_targets.json settings/insulin_sensitivities.json settings/basal_profile.json preferences.json settings/carb_ratios.json settings/temptargets.json settings/model.json
-//для profile.json параметры: settings/settings.json settings/bg_targets.json settings/insulin_sensitivities.json settings/basal_profile.json preferences.json settings/carb_ratios.json settings/temptargets.json settings/model.json settings/autotune.json
-
-function generate(pumpsettings_data, bgtargets_data, isf_data, basalprofile_data, preferences_input = false, carbratio_input = false, temptargets_input = false, model_input = false, autotune_input = false, trio_data, clock_input = false) {
-    if (bgtargets_data.units !== 'mg/dL') {
-        if (bgtargets_data.units === 'mmol/L') {
-            for (var i = 0, len = bgtargets_data.targets.length; i < len; i++) {
-                bgtargets_data.targets[i].high = bgtargets_data.targets[i].high * 18;
-                bgtargets_data.targets[i].low = bgtargets_data.targets[i].low * 18;
-            }
-            bgtargets_data.units = 'mg/dL';
-        } else {
-            return { "error" : 'BG Target data is expected to be expressed in mg/dL or mmol/L. Found '+ bgtargets_data.units };
-        }
-    }
-    
-    if (isf_data.units !== 'mg/dL') {
-        if (isf_data.units === 'mmol/L') {
-            for (var i = 0, len = isf_data.sensitivities.length; i < len; i++) {
-                isf_data.sensitivities[i].sensitivity = isf_data.sensitivities[i].sensitivity * 18;
-            }
-            isf_data.units = 'mg/dL';
-        } else {
-            return { "error" : 'ISF is expected to be expressed in mg/dL or mmol/L. Found '+ isf_data.units };
-        }
-    }
-
-    var autotune_data = { };
-    if (autotune_input) {
-        autotune_data = autotune_input;
-    }
-
-    var temptargets_data = { };
-    if (temptargets_input) {
-        temptargets_data = temptargets_input;
-    }
-    
-    var trioData = { };
-    if (trio_data) {
-        trioData = trio_data;
-    }
-
-    var clock = null;
-    if (clock_input) {
-        clock = new Date(clock_input);
-    }
-
-    var model_data = { };
-    if (model_input) {
-        model_data = model_input.replace(/"/gi, '');
-    }
-
-    var carbratio_data = { };
-    if (carbratio_input) {
-        var errors = [ ];
-        if (!(carbratio_input.schedule && carbratio_input.schedule[0].start && carbratio_input.schedule[0].ratio)) {
-          errors.push("Carb ratio data should have an array called schedule with a start and ratio fields.");
-        }
-        if (carbratio_input.units !== 'grams' && carbratio_input.units !== 'exchanges')  {
-          errors.push("Carb ratio should have units field set to 'grams' or 'exchanges'.");
-        }
-        if (errors.length) {
-          return { "error" : errors.join(' ') };
-        }
-        carbratio_data = carbratio_input;
-    }
-
-    var preferences = { };
-    if (preferences_input) {
-        preferences = preferences_input;
-        if (preferences.curve === "rapid-acting") {
-            if (preferences.useCustomPeakTime) {
-                preferences.insulinPeakTime =
-                Math.max(50, Math.min(preferences.insulinPeakTime, 120));
-            } else { preferences.insulinPeakTime = 75; }
-        } 
-        else if (preferences.curve === "ultra-rapid") {
-            if (preferences.useCustomPeakTime) {
-                preferences.insulinPeakTime =
-                Math.max(35, Math.min(preferences.insulinPeakTime, 100));
-            } else { preferences.insulinPeakTime = 55; }
-        }
-    }
-
-    var inputs = { };
-    //add all preferences to the inputs
-    for (var pref in preferences) {
-      if (preferences.hasOwnProperty(pref)) {
-        inputs[pref] = preferences[pref];
-      }
-    }
-
-    inputs.max_iob = inputs.max_iob || 0;
-    //set these after to make sure nothing happens if they are also set in preferences
-    inputs.settings = pumpsettings_data;
-    inputs.targets = bgtargets_data;
-    inputs.basals = basalprofile_data;
-    inputs.isf = isf_data;
-    inputs.carbratio = carbratio_data;
-    inputs.temptargets = temptargets_data;
-    inputs.model = model_data;
-    inputs.autotune = autotune_data;
-    inputs.clock = clock;
-
-    if (autotune_data) {
-        if (autotune_data.basalprofile) { inputs.basals = autotune_data.basalprofile; }
-        if (!trioData.onlyAutotuneBasals) {
-            if (autotune_data.isfProfile) { inputs.isf = autotune_data.isfProfile; }
-            if (autotune_data.carb_ratio) { inputs.carbratio.schedule[0].ratio = autotune_data.carb_ratio; }
-        }
-    }
-    return trio_profile(inputs);
-}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 2
TrioTests/OpenAPSSwiftTests/javascript/bundle/profile.js


+ 0 - 42
TrioTests/OpenAPSSwiftTests/utils/HttpFiles.swift

@@ -1,42 +0,0 @@
-import Foundation
-@testable import Trio
-
-/// Helper struct to download files from localhost via HTTP. Must have a HTTP server
-/// running on port 8123 that supports listing files and downloading files.
-///
-/// You can set two ReplayTests variables `HTTP_FILES_OFFSET` and `HTTP_FILES_LENGTH`
-/// to implement paging
-///
-/// This struct is only useful during testing as it is missing a number of error checks
-struct HttpFiles {
-    static func listFiles() async throws -> [String] {
-        let url = URL(string: "http://localhost:8123/list")!
-        let (data, _) = try await URLSession.shared.data(from: url)
-        let allFiles = try JSONDecoder().decode([String].self, from: data)
-
-        let files: [String]
-        if let offset = ReplayTests.filesOffset, let length = ReplayTests.filesLength
-        {
-            // Both variables exist and are valid integers
-            let endIndex = min(offset + length, allFiles.count)
-            let startIndex = min(offset, allFiles.count)
-            files = Array(allFiles[startIndex ..< endIndex])
-        } else {
-            files = allFiles
-        }
-
-        if files.count > 5000 {
-            fatalError("too many files: \(files.count) \(ProcessInfo.processInfo.environment)")
-        }
-
-        return files
-    }
-
-    static func downloadFile(at: String) async throws -> AlgorithmComparison {
-        let decoder = JSONDecoder()
-        decoder.dateDecodingStrategy = .secondsSince1970
-        let dataUrl = URL(string: "http://localhost:8123\(at)")!
-        let (data, _) = try await URLSession.shared.data(from: dataUrl)
-        return try decoder.decode(AlgorithmComparison.self, from: data)
-    }
-}

+ 0 - 162
TrioTests/OpenAPSSwiftTests/utils/IobJsonTypes.swift

@@ -1,162 +0,0 @@
-import Foundation
-@testable import Trio
-
-protocol BaseHistoryRecord {
-    var date: UInt64 { get }
-}
-
-// For insulin bolus records
-struct InsulinRecord: BaseHistoryRecord, Codable {
-    let insulin: Decimal
-    let date: UInt64
-    let created_at: Date?
-    let started_at: Date?
-    let timestamp: Date?
-
-    enum CodingKeys: String, CodingKey {
-        case insulin
-        case date
-        case created_at
-        case started_at
-        case timestamp
-    }
-
-    func mismatch(field: String, record: ComputedPumpHistoryEvent) -> Bool {
-        print("Insulin mismatch \(field) json date: \(date) swift: \(record.date)")
-        return false
-    }
-
-    func matches(record: ComputedPumpHistoryEvent) -> Bool {
-        if insulin != record.insulin {
-            return mismatch(field: "insulin", record: record)
-        }
-
-        if date != record.date, (date - 1) != record.date {
-            return mismatch(field: "date", record: record)
-        }
-
-        if let timestamp = timestamp, timestamp != record.timestamp {
-            return mismatch(field: "timestamp", record: record)
-        }
-
-        if let started_at = started_at, started_at != record.started_at {
-            return mismatch(field: "started_at", record: record)
-        }
-
-        return true
-    }
-}
-
-// For temporary basal rate records
-struct BasalRateRecord: BaseHistoryRecord, Codable {
-    let rate: Decimal
-    let timestamp: Date?
-    let started_at: Date?
-    let date: UInt64
-    let duration: Decimal
-
-    enum CodingKeys: String, CodingKey {
-        case rate
-        case timestamp
-        case started_at
-        case date
-        case duration
-    }
-
-    func mismatch(field: String, record: ComputedPumpHistoryEvent) -> Bool {
-        print("Basal mismatch \(field) json date: \(date) swift: \(record.date)")
-        return false
-    }
-
-    func matches(record: ComputedPumpHistoryEvent) -> Bool {
-        if rate != record.rate! {
-            return mismatch(field: "rate", record: record)
-        }
-
-        if date != record.date {
-            return mismatch(field: "date", record: record)
-        }
-
-        if !duration.isWithin(0.00001, of: record.duration!) {
-            return mismatch(field: "duration", record: record)
-        }
-
-        if let timestamp = timestamp, timestamp != record.timestamp {
-            return mismatch(field: "timestamp", record: record)
-        }
-
-        if let started_at = started_at, started_at != record.started_at {
-            return mismatch(field: "started_at", record: record)
-        }
-
-        return true
-    }
-}
-
-// Helper enum to handle either type of record
-enum HistoryRecord: Decodable {
-    case insulin(InsulinRecord)
-    case basal(BasalRateRecord)
-
-    init(from decoder: Decoder) throws {
-        let container = try decoder.container(keyedBy: CodingKeys.self)
-
-        let date: UInt64
-        if let doubleDate = try? container.decode(Double.self, forKey: .date) {
-            date = UInt64(doubleDate)
-        } else {
-            date = try container.decode(UInt64.self, forKey: .date)
-        }
-
-        // If not basal, it must be insulin - check for insulin value
-        if let insulin = try? container.decode(Decimal.self, forKey: .insulin) {
-            // Handle both formats of insulin records
-            let created_at = try? container.decode(Date.self, forKey: .created_at)
-            let timestamp = try? container.decode(Date.self, forKey: .timestamp)
-            let started_at = try? container.decode(Date.self, forKey: .started_at)
-
-            self = .insulin(InsulinRecord(
-                insulin: insulin,
-                date: date,
-                created_at: created_at,
-                started_at: started_at,
-                timestamp: timestamp
-            ))
-            return
-        }
-
-        // Otherwise, try to decode as basal record
-        let rate = try container.decode(Decimal.self, forKey: .rate)
-        let timestamp = try? container.decode(Date.self, forKey: .timestamp)
-        let started_at = try? container.decode(Date.self, forKey: .started_at)
-        let duration = try container.decode(Decimal.self, forKey: .duration)
-
-        self = .basal(BasalRateRecord(
-            rate: rate,
-            timestamp: timestamp,
-            started_at: started_at,
-            date: date,
-            duration: duration
-        ))
-    }
-
-    func matches(_ event: ComputedPumpHistoryEvent) -> Bool {
-        switch self {
-        case let .insulin(record):
-            return record.matches(record: event)
-
-        case let .basal(record):
-            return record.matches(record: event)
-        }
-    }
-
-    private enum CodingKeys: String, CodingKey {
-        case insulin
-        case date
-        case created_at
-        case rate
-        case timestamp
-        case started_at
-        case duration
-    }
-}

+ 0 - 292
TrioTests/OpenAPSSwiftTests/utils/OpenAPSFixed.swift

@@ -1,292 +0,0 @@
-import Combine
-import Foundation
-import JavaScriptCore
-
-@testable import Trio
-
-/// This class provides us with an implementation of trio-oref with a number of iob bugs that are fixed.
-/// We can use this during testing to confirm that for an input that generated an error that a corrected
-/// Javascript implementation would have produced the same results
-final class OpenAPSFixed {
-    func sortPumpHistory(pumpHistory: JSON) throws -> JSON {
-        let pumpHistorySwift = try JSONBridge.pumpHistory(from: pumpHistory)
-        return try JSONBridge.to(pumpHistorySwift.sorted(by: { $0.timestamp > $1.timestamp }))
-    }
-
-    private func middlewareScript(name: String) -> Script? {
-        if let url = Foundation.Bundle.main.url(forResource: "javascript/\(name)", withExtension: "") {
-            do {
-                let body = try String(contentsOf: url)
-                return Script(name: name, body: body)
-            } catch {
-                debug(.openAPS, "Failed to load script \(name): \(error)")
-            }
-        }
-
-        return nil
-    }
-
-    func determineBasalJavascript(
-        glucose: JSON,
-        currentTemp: JSON,
-        iob: JSON,
-        profile: JSON,
-        autosens: JSON,
-        meal: JSON,
-        microBolusAllowed: Bool,
-        reservoir: JSON,
-        pumpHistory: JSON,
-        preferences: JSON,
-        basalProfile: JSON,
-        trioCustomOrefVariables: JSON,
-        clock: Date
-    ) async throws -> OrefFunctionResult {
-        do {
-            let jsWorker = JavaScriptWorker(poolSize: 1)
-            let testBundle = Bundle(for: OpenAPSFixed.self)
-            let result = try await withCheckedThrowingContinuation { continuation in
-                jsWorker.inCommonContext { worker in
-                    worker.evaluateBatch(scripts: [
-                        Script(name: "prepare/log.js"),
-                        Script.fromTestingBundle(name: "determine-basal-prepare.js", bundle: testBundle),
-                        Script.fromTestingBundle(name: "basal-set-temp.js", bundle: testBundle),
-                        Script.fromTestingBundle(name: "glucose-get-last.js", bundle: testBundle),
-                        Script.fromTestingBundle(name: "determine-basal.js", bundle: testBundle)
-                    ])
-
-                    if let middleware = self.middlewareScript(name: OpenAPS.Middleware.determineBasal) {
-                        worker.evaluate(script: middleware)
-                    }
-
-                    let result = worker.call(function: "generate", with: [
-                        iob,
-                        currentTemp,
-                        glucose,
-                        profile,
-                        autosens,
-                        meal,
-                        microBolusAllowed,
-                        reservoir,
-                        clock,
-                        pumpHistory,
-                        preferences,
-                        basalProfile,
-                        trioCustomOrefVariables
-                    ])
-
-                    continuation.resume(returning: result)
-                }
-            }
-            return .success(result)
-        } catch {
-            return .failure(error)
-        }
-    }
-
-    func iobHistory(pumphistory: JSON, profile: JSON, clock: JSON, autosens: JSON, zeroTempDuration: JSON) async throws -> JSON {
-        let jsWorker = JavaScriptWorker(poolSize: 1)
-        let testBundle = Bundle(for: OpenAPSFixed.self)
-        let pumphistory: JSON = try! sortPumpHistory(pumpHistory: pumphistory)
-        let result = try await withCheckedThrowingContinuation { continuation in
-            jsWorker.inCommonContext { worker in
-                worker.evaluateBatch(scripts: [
-                    Script(name: "prepare/log.js"),
-                    Script.fromTestingBundle(name: "iob-history.js", bundle: testBundle),
-                    Script.fromTestingBundle(name: "iob-history-prepare.js", bundle: testBundle)
-                ])
-
-                let result = worker.call(function: "generate", with: [
-                    pumphistory,
-                    profile,
-                    clock,
-                    autosens,
-                    zeroTempDuration
-                ])
-                continuation.resume(returning: result)
-            }
-        }
-        return result
-    }
-
-    func mealJavascript(
-        pumphistory: JSON,
-        profile: JSON,
-        basalProfile: JSON,
-        clock: JSON,
-        carbs: JSON,
-        glucose: JSON
-    ) async -> OrefFunctionResult {
-        let jsWorker = JavaScriptWorker(poolSize: 1)
-        let testBundle = Bundle(for: OpenAPSFixed.self)
-        do {
-            let result = try await withCheckedThrowingContinuation { continuation in
-                jsWorker.inCommonContext { worker in
-                    worker.evaluateBatch(scripts: [
-                        Script(name: "prepare/log.js"),
-                        Script.fromTestingBundle(name: "meal.js", bundle: testBundle),
-                        Script.fromTestingBundle(name: "meal-prepare.js", bundle: testBundle)
-                    ])
-                    let result = worker.call(function: "generate", with: [
-                        pumphistory,
-                        profile,
-                        clock,
-                        glucose,
-                        basalProfile,
-                        carbs
-                    ])
-                    continuation.resume(returning: result)
-                }
-            }
-            return .success(result)
-        } catch {
-            return .failure(error)
-        }
-    }
-
-    static let prepare = "autosens-prepare.js"
-    static let prepare24 = "autosens-prepare-24.js"
-    static let prepare8 = "autosens-prepare-8.js"
-
-    func autosenseJavascript(
-        glucose: JSON,
-        pumpHistory: JSON,
-        basalprofile: JSON,
-        profile: JSON,
-        carbs: JSON,
-        temptargets: JSON,
-        clock: JSON,
-        prepareFile: String
-    ) async -> OrefFunctionResult {
-        do {
-            let result = try await withCheckedThrowingContinuation { continuation in
-                let jsWorker = JavaScriptWorker(poolSize: 1)
-                let testBundle = Bundle(for: OpenAPSFixed.self)
-                jsWorker.inCommonContext { worker in
-                    worker.evaluateBatch(scripts: [
-                        Script(name: "prepare/log.js"),
-                        Script.fromTestingBundle(name: "autosens.js", bundle: testBundle),
-                        Script.fromTestingBundle(name: prepareFile, bundle: testBundle)
-                    ])
-                    let result = worker.call(function: "generate", with: [
-                        glucose,
-                        pumpHistory,
-                        basalprofile,
-                        profile,
-                        carbs,
-                        temptargets,
-                        clock
-                    ])
-                    continuation.resume(returning: result)
-                }
-            }
-            return .success(result)
-        } catch {
-            return .failure(error)
-        }
-    }
-
-    func iobJavascript(pumphistory: JSON, profile: JSON, clock: JSON, autosens: JSON) async -> OrefFunctionResult {
-        do {
-            let testBundle = Bundle(for: OpenAPSFixed.self)
-            let pumphistory: JSON = try! sortPumpHistory(pumpHistory: pumphistory)
-            let result = try await withCheckedThrowingContinuation { continuation in
-                let jsWorker = JavaScriptWorker(poolSize: 1)
-                jsWorker.inCommonContext { worker in
-                    worker.evaluateBatch(scripts: [
-                        Script(name: "prepare/log.js"),
-                        Script.fromTestingBundle(name: "iob.js", bundle: testBundle),
-                        Script(name: "prepare/iob.js")
-                    ])
-                    let result = worker.call(function: "generate", with: [
-                        pumphistory,
-                        profile,
-                        clock,
-                        autosens
-                    ])
-                    continuation.resume(returning: result)
-                }
-            }
-            return .success(result)
-        } catch {
-            return .failure(error)
-        }
-    }
-
-    func makeProfileJavascript(
-        preferences: JSON,
-        pumpSettings: JSON,
-        bgTargets: JSON,
-        basalProfile: JSON,
-        isf: JSON,
-        carbRatio: JSON,
-        tempTargets: JSON,
-        model: JSON,
-        autotune: JSON,
-        trioSettings: JSON,
-        clock: JSON
-    ) async -> OrefFunctionResult {
-        do {
-            let testBundle = Bundle(for: OpenAPSFixed.self)
-            let result = try await withCheckedThrowingContinuation { continuation in
-                let jsWorker = JavaScriptWorker(poolSize: 1)
-                jsWorker.inCommonContext { worker in
-                    worker.evaluateBatch(scripts: [
-                        Script(name: "prepare/log.js"),
-                        Script.fromTestingBundle(name: "profile.js", bundle: testBundle),
-                        Script.fromTestingBundle(name: "profile-prepare.js", bundle: testBundle)
-                    ])
-                    let result = worker.call(function: "generate", with: [
-                        pumpSettings,
-                        bgTargets,
-                        isf,
-                        basalProfile,
-                        preferences,
-                        carbRatio,
-                        tempTargets,
-                        model,
-                        autotune,
-                        trioSettings,
-                        clock
-                    ])
-                    continuation.resume(returning: result)
-                }
-            }
-            return .success(result)
-        } catch {
-            return .failure(error)
-        }
-    }
-}
-
-extension Script {
-    static func fromTestingBundle(name: String, bundle: Bundle) -> Script {
-        let body: String
-        if let url = bundle.url(forResource: "\(name)", withExtension: "") {
-            do {
-                body = try String(contentsOf: url)
-            } catch {
-                print("Error loading script: \(error.localizedDescription)")
-                body = "Error loading script"
-            }
-        } else {
-            print("Resource not found: javascript/\(name)")
-            testPrintAllJSFiles(testBundle: bundle)
-            body = "Resource not found"
-        }
-        return Script(name: name, body: body)
-    }
-
-    static func testPrintAllJSFiles(testBundle: Bundle) {
-        // Get all .js files in the bundle
-        if let jsURLs = testBundle.urls(forResourcesWithExtension: "js", subdirectory: nil) {
-            print("JavaScript files in test bundle:")
-            for jsURL in jsURLs {
-                print("- \(jsURL.lastPathComponent)")
-                print("  Full path: \(jsURL.path)")
-            }
-            print("Total JS files found: \(jsURLs.count)")
-        } else {
-            print("No JavaScript files found in test bundle")
-        }
-    }
-}

+ 0 - 73
TrioTests/OpenAPSSwiftTests/utils/ReplayTests.swift

@@ -1,73 +0,0 @@
-import Foundation
-
-enum ReplayTests {
-    /// Flag to enable replay tests.
-    ///
-    /// These test are only used for debugging so normally they should be disabled. But
-    /// if you're debugging the oref-swift functions they are extremely useful. To enable them
-    /// add these lines to your ConfigOverride.xcconfig file:
-    /// ```
-    /// ENABLE_REPLAY_TESTS = YES
-    /// ```
-    static var enabled: Bool {
-        let env = ProcessInfo.processInfo.environment
-        if env["ENABLE_REPLAY_TESTS"] == "YES" {
-            return true
-        }
-
-        let bundle = Bundle(for: BundleReference.self)
-        return bundle.object(forInfoDictionaryKey: "EnableReplayTests") as? String == "YES"
-    }
-
-    /// The offset for pagination of replay input files
-    ///
-    /// Set this offset using an environment variable or the ConfigOverride.xcconfig file.
-    /// For this change to take effect you must also set the length
-    /// ```
-    /// HTTP_FILES_OFFSET = 2000
-    /// ```
-    static var filesOffset: Int? {
-        let env = ProcessInfo.processInfo.environment
-        if let offset = env["HTTP_FILES_OFFSET"].flatMap({ Int($0) }) {
-            return offset
-        }
-
-        let bundle = Bundle(for: BundleReference.self)
-        let offsetString = bundle.object(forInfoDictionaryKey: "HttpFilesOffset") as? String
-        return offsetString.flatMap { Int($0) }
-    }
-
-    /// Length for pagination of replay input files
-    ///
-    /// Set this length using an environment variable or the ConfigOverride.xcconfig file.
-    /// ```
-    /// HTTP_FILES_LENGTH = 3500
-    /// ```
-    static var filesLength: Int? {
-        let env = ProcessInfo.processInfo.environment
-        if let length = env["HTTP_FILES_LENGTH"].flatMap({ Int($0) }) {
-            return length
-        }
-
-        let bundle = Bundle(for: BundleReference.self)
-        let lengthString = bundle.object(forInfoDictionaryKey: "HttpFilesLength") as? String
-        return lengthString.flatMap { Int($0) }
-    }
-
-    /// Timezone to use for replay tests.
-    ///
-    /// This is used to filter replay test files by timezone. If not set, it defaults to "America/Los_Angeles".
-    /// To set it, add this line to your ConfigOverride.xcconfig file:
-    /// ```
-    /// REPLAY_TEST_TIMEZONE = Europe/Berlin
-    /// ```
-    static var timezone: String {
-        let env = ProcessInfo.processInfo.environment
-        if let timezone = env["REPLAY_TEST_TIMEZONE"], !timezone.isEmpty {
-            return timezone
-        }
-
-        let bundle = Bundle(for: BundleReference.self)
-        return bundle.object(forInfoDictionaryKey: "ReplayTestTimezone") as? String ?? "America/Los_Angeles"
-    }
-}

+ 0 - 42
TrioTests/OpenAPSSwiftTests/utils/TimeZoneForTests.swift

@@ -1,42 +0,0 @@
-import Foundation
-
-class TimeZoneForTests {
-    private var originalTZ: String? = ProcessInfo.processInfo.environment["TZ"]
-    private var originalDefaultTimeZone: TimeZone? = TimeZone.current
-
-    // Helper function to set timezone
-    func setTimezone(identifier: String) {
-        // Set environment variable
-        setenv("TZ", identifier, 1)
-        tzset() // Make the change take effect
-        CFTimeZoneResetSystem()
-
-        // Force update the default TimeZone
-        // This is the critical missing piece
-        if let timeZone = TimeZone(identifier: identifier) {
-            TimeZone.ReferenceType.default = timeZone
-
-            // For extra assurance, you can log to verify
-            print("Timezone set to: \(TimeZone.current.identifier)")
-        } else {
-            print("Failed to create TimeZone with identifier: \(identifier)")
-        }
-    }
-
-    // Helper function to reset timezone
-    func resetTimezone() {
-        // Restore system timezone from environment
-        if let originalTZ = originalTZ {
-            setenv("TZ", originalTZ, 1)
-        } else {
-            unsetenv("TZ")
-        }
-        tzset()
-        CFTimeZoneResetSystem()
-
-        // Restore original default TimeZone
-        if let originalTimeZone = originalDefaultTimeZone {
-            TimeZone.ReferenceType.default = originalTimeZone
-        }
-    }
-}