OpenAPSFixed.swift 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import Combine
  2. import Foundation
  3. import JavaScriptCore
  4. @testable import Trio
  5. /// This class provides us with an implementation of trio-oref with a number of iob bugs that are fixed.
  6. /// We can use this during testing to confirm that for an input that generated an error that a corrected
  7. /// Javascript implementation would have produced the same results
  8. final class OpenAPSFixed {
  9. func sortPumpHistory(pumpHistory: JSON) throws -> JSON {
  10. let pumpHistorySwift = try JSONBridge.pumpHistory(from: pumpHistory)
  11. return try JSONBridge.to(pumpHistorySwift.sorted(by: { $0.timestamp > $1.timestamp }))
  12. }
  13. func iobHistory(pumphistory: JSON, profile: JSON, clock: JSON, autosens: JSON, zeroTempDuration: JSON) async throws -> JSON {
  14. let jsWorker = JavaScriptWorker(poolSize: 1)
  15. let testBundle = Bundle(for: OpenAPSFixed.self)
  16. let pumphistory: JSON = try! sortPumpHistory(pumpHistory: pumphistory)
  17. let result = try await withCheckedThrowingContinuation { continuation in
  18. jsWorker.inCommonContext { worker in
  19. worker.evaluateBatch(scripts: [
  20. Script(name: "prepare/log.js"),
  21. Script.fromTestingBundle(name: "iob-history.js", bundle: testBundle),
  22. Script.fromTestingBundle(name: "iob-history-prepare.js", bundle: testBundle)
  23. ])
  24. let result = worker.call(function: "generate", with: [
  25. pumphistory,
  26. profile,
  27. clock,
  28. autosens,
  29. zeroTempDuration
  30. ])
  31. continuation.resume(returning: result)
  32. }
  33. }
  34. return result
  35. }
  36. func mealJavascript(
  37. pumphistory: JSON,
  38. profile: JSON,
  39. basalProfile: JSON,
  40. clock: JSON,
  41. carbs: JSON,
  42. glucose: JSON
  43. ) async -> OrefFunctionResult {
  44. let jsWorker = JavaScriptWorker(poolSize: 1)
  45. let testBundle = Bundle(for: OpenAPSFixed.self)
  46. do {
  47. let result = try await withCheckedThrowingContinuation { continuation in
  48. jsWorker.inCommonContext { worker in
  49. worker.evaluateBatch(scripts: [
  50. Script(name: "prepare/log.js"),
  51. Script.fromTestingBundle(name: "meal.js", bundle: testBundle),
  52. Script(name: "prepare/meal.js")
  53. ])
  54. let result = worker.call(function: "generate", with: [
  55. pumphistory,
  56. profile,
  57. clock,
  58. glucose,
  59. basalProfile,
  60. carbs
  61. ])
  62. continuation.resume(returning: result)
  63. }
  64. }
  65. return .success(result)
  66. } catch {
  67. return .failure(error)
  68. }
  69. }
  70. func autosenseJavascript(
  71. glucose: JSON,
  72. pumpHistory: JSON,
  73. basalprofile: JSON,
  74. profile: JSON,
  75. carbs: JSON,
  76. temptargets: JSON,
  77. clock: JSON
  78. ) async -> OrefFunctionResult {
  79. do {
  80. let result = try await withCheckedThrowingContinuation { continuation in
  81. let jsWorker = JavaScriptWorker(poolSize: 1)
  82. let testBundle = Bundle(for: OpenAPSFixed.self)
  83. jsWorker.inCommonContext { worker in
  84. worker.evaluateBatch(scripts: [
  85. Script(name: "prepare/log.js"),
  86. Script.fromTestingBundle(name: "autosens.js", bundle: testBundle),
  87. Script.fromTestingBundle(name: "autosens-prepare.js", bundle: testBundle)
  88. ])
  89. let result = worker.call(function: "generate", with: [
  90. glucose,
  91. pumpHistory,
  92. basalprofile,
  93. profile,
  94. carbs,
  95. temptargets,
  96. clock
  97. ])
  98. continuation.resume(returning: result)
  99. }
  100. }
  101. return .success(result)
  102. } catch {
  103. return .failure(error)
  104. }
  105. }
  106. func iobJavascript(pumphistory: JSON, profile: JSON, clock: JSON, autosens: JSON) async -> OrefFunctionResult {
  107. do {
  108. let testBundle = Bundle(for: OpenAPSFixed.self)
  109. let pumphistory: JSON = try! sortPumpHistory(pumpHistory: pumphistory)
  110. let result = try await withCheckedThrowingContinuation { continuation in
  111. let jsWorker = JavaScriptWorker(poolSize: 1)
  112. jsWorker.inCommonContext { worker in
  113. worker.evaluateBatch(scripts: [
  114. Script(name: "prepare/log.js"),
  115. Script.fromTestingBundle(name: "iob.js", bundle: testBundle),
  116. Script(name: "prepare/iob.js")
  117. ])
  118. let result = worker.call(function: "generate", with: [
  119. pumphistory,
  120. profile,
  121. clock,
  122. autosens
  123. ])
  124. continuation.resume(returning: result)
  125. }
  126. }
  127. return .success(result)
  128. } catch {
  129. return .failure(error)
  130. }
  131. }
  132. }
  133. extension Script {
  134. static func fromTestingBundle(name: String, bundle: Bundle) -> Script {
  135. let body: String
  136. if let url = bundle.url(forResource: "\(name)", withExtension: "") {
  137. do {
  138. body = try String(contentsOf: url)
  139. } catch {
  140. print("Error loading script: \(error.localizedDescription)")
  141. body = "Error loading script"
  142. }
  143. } else {
  144. print("Resource not found: javascript/\(name)")
  145. testPrintAllJSFiles(testBundle: bundle)
  146. body = "Resource not found"
  147. }
  148. return Script(name: name, body: body)
  149. }
  150. static func testPrintAllJSFiles(testBundle: Bundle) {
  151. // Get all .js files in the bundle
  152. if let jsURLs = testBundle.urls(forResourcesWithExtension: "js", subdirectory: nil) {
  153. print("JavaScript files in test bundle:")
  154. for jsURL in jsURLs {
  155. print("- \(jsURL.lastPathComponent)")
  156. print(" Full path: \(jsURL.path)")
  157. }
  158. print("Total JS files found: \(jsURLs.count)")
  159. } else {
  160. print("No JavaScript files found in test bundle")
  161. }
  162. }
  163. }