@vived/app 6.7.1 → 6.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/README.md +145 -1
  2. package/dist/cjs/BaseApp/UC/RenderCanvasUC.js.map +1 -1
  3. package/dist/cjs/BaseApp/UC/RenderCanvasUC.test.js.map +1 -1
  4. package/dist/cjs/Challenge/Factories/ChallengeFeatureFactory.js.map +1 -1
  5. package/dist/cjs/Challenge/Factories/ChallengeFeatureFactory.test.js.map +1 -1
  6. package/dist/cjs/Dispatcher/Factories/DispatcherFeatureFactory.js +4 -3
  7. package/dist/cjs/Dispatcher/Factories/DispatcherFeatureFactory.js.map +1 -1
  8. package/dist/cjs/Dispatcher/Factories/DispatcherFeatureFactory.test.js +35 -0
  9. package/dist/cjs/Dispatcher/Factories/DispatcherFeatureFactory.test.js.map +1 -0
  10. package/dist/cjs/Dispatcher/Factories/setupDispatchers.js +1 -0
  11. package/dist/cjs/Dispatcher/Factories/setupDispatchers.js.map +1 -1
  12. package/dist/cjs/Dispatcher/Factories/setupDispatchers.test.js +33 -0
  13. package/dist/cjs/Dispatcher/Factories/setupDispatchers.test.js.map +1 -0
  14. package/dist/cjs/EventSystem/Entities/EventEntity.js.map +1 -1
  15. package/dist/cjs/EventSystem/Entities/EventEntity.test.js +4 -1
  16. package/dist/cjs/EventSystem/Entities/EventEntity.test.js.map +1 -1
  17. package/dist/cjs/EventSystem/Entities/index.js.map +1 -1
  18. package/dist/cjs/EventSystem/EventSystem.integration.test.js.map +1 -1
  19. package/dist/cjs/EventSystem/Factories/EventSystemFeatureFactory.js.map +1 -1
  20. package/dist/cjs/EventSystem/Factories/EventSystemFeatureFactory.test.js.map +1 -1
  21. package/dist/cjs/EventSystem/Factories/index.js.map +1 -1
  22. package/dist/cjs/EventSystem/Mocks/MockEventEntity.js.map +1 -1
  23. package/dist/cjs/EventSystem/Mocks/index.js.map +1 -1
  24. package/dist/cjs/EventSystem/index.js.map +1 -1
  25. package/dist/cjs/EventSystem/types.js.map +1 -1
  26. package/dist/cjs/LabelDrop/Factories/LabelDropFeatureFactory.js.map +1 -1
  27. package/dist/cjs/LabelDrop/UseCases/SubmitLabelDropResultUC.js.map +1 -1
  28. package/dist/cjs/LabelDrop/UseCases/SubmitLabelDropResultUC.test.js.map +1 -1
  29. package/dist/cjs/LabelDrop/UseCases/index.js.map +1 -1
  30. package/dist/cjs/Procedure/Adapters/index.js.map +1 -1
  31. package/dist/cjs/Procedure/Adapters/procedureAdapter.js.map +1 -1
  32. package/dist/cjs/Procedure/Adapters/procedureAdapter.test.js.map +1 -1
  33. package/dist/cjs/Procedure/Adapters/procedureAuthoringAdapter.js.map +1 -1
  34. package/dist/cjs/Procedure/Adapters/procedureAuthoringAdapter.test.js.map +1 -1
  35. package/dist/cjs/Procedure/Adapters/procedureHintAdapter.js.map +1 -1
  36. package/dist/cjs/Procedure/Adapters/procedureHintAdapter.test.js.map +1 -1
  37. package/dist/cjs/Procedure/Adapters/procedureProgressAdapter.js.map +1 -1
  38. package/dist/cjs/Procedure/Adapters/procedureProgressAdapter.test.js.map +1 -1
  39. package/dist/cjs/Procedure/Adapters/procedureQuizResultAdapter.js.map +1 -1
  40. package/dist/cjs/Procedure/Adapters/procedureQuizResultAdapter.test.js +3 -1
  41. package/dist/cjs/Procedure/Adapters/procedureQuizResultAdapter.test.js.map +1 -1
  42. package/dist/cjs/Procedure/Entities/HintRegistry.js.map +1 -1
  43. package/dist/cjs/Procedure/Entities/HintRegistry.test.js.map +1 -1
  44. package/dist/cjs/Procedure/Entities/ProcedureEntity.js.map +1 -1
  45. package/dist/cjs/Procedure/Entities/ProcedureEntity.test.js +1 -12
  46. package/dist/cjs/Procedure/Entities/ProcedureEntity.test.js.map +1 -1
  47. package/dist/cjs/Procedure/Entities/index.js.map +1 -1
  48. package/dist/cjs/Procedure/Factories/ProcedureFeatureFactory.js.map +1 -1
  49. package/dist/cjs/Procedure/Factories/ProcedureFeatureFactory.test.js +3 -1
  50. package/dist/cjs/Procedure/Factories/ProcedureFeatureFactory.test.js.map +1 -1
  51. package/dist/cjs/Procedure/Factories/index.js.map +1 -1
  52. package/dist/cjs/Procedure/Mocks/MockProcedureEntity.js.map +1 -1
  53. package/dist/cjs/Procedure/Mocks/MockProcedurePM.js.map +1 -1
  54. package/dist/cjs/Procedure/Mocks/index.js.map +1 -1
  55. package/dist/cjs/Procedure/PM/ProcedurePM.js.map +1 -1
  56. package/dist/cjs/Procedure/PM/ProcedurePM.test.js +1 -1
  57. package/dist/cjs/Procedure/PM/ProcedurePM.test.js.map +1 -1
  58. package/dist/cjs/Procedure/PM/index.js.map +1 -1
  59. package/dist/cjs/Procedure/ProcedureEventSystem.integration.test.js.map +1 -1
  60. package/dist/cjs/Procedure/UCs/AddProcedureEventUC.js.map +1 -1
  61. package/dist/cjs/Procedure/UCs/AddProcedureEventUC.test.js +1 -4
  62. package/dist/cjs/Procedure/UCs/AddProcedureEventUC.test.js.map +1 -1
  63. package/dist/cjs/Procedure/UCs/MoveProcedureEventDownUC.js.map +1 -1
  64. package/dist/cjs/Procedure/UCs/MoveProcedureEventDownUC.test.js.map +1 -1
  65. package/dist/cjs/Procedure/UCs/MoveProcedureEventUpUC.js.map +1 -1
  66. package/dist/cjs/Procedure/UCs/MoveProcedureEventUpUC.test.js.map +1 -1
  67. package/dist/cjs/Procedure/UCs/RecordProcedureEventUC.js.map +1 -1
  68. package/dist/cjs/Procedure/UCs/RecordProcedureEventUC.test.js.map +1 -1
  69. package/dist/cjs/Procedure/UCs/RecordProcedureSessionUC.js.map +1 -1
  70. package/dist/cjs/Procedure/UCs/RecordProcedureSessionUC.test.js +22 -4
  71. package/dist/cjs/Procedure/UCs/RecordProcedureSessionUC.test.js.map +1 -1
  72. package/dist/cjs/Procedure/UCs/RemoveProcedureEventUC.js.map +1 -1
  73. package/dist/cjs/Procedure/UCs/RemoveProcedureEventUC.test.js.map +1 -1
  74. package/dist/cjs/Procedure/UCs/ResetProcedureProgressUC.js.map +1 -1
  75. package/dist/cjs/Procedure/UCs/ResetProcedureProgressUC.test.js.map +1 -1
  76. package/dist/cjs/Procedure/UCs/SerializeProcedure.js.map +1 -1
  77. package/dist/cjs/Procedure/UCs/SerializeProcedure.test.js +6 -1
  78. package/dist/cjs/Procedure/UCs/SerializeProcedure.test.js.map +1 -1
  79. package/dist/cjs/Procedure/UCs/SetProcedureIsQuizUC.js.map +1 -1
  80. package/dist/cjs/Procedure/UCs/SetProcedureIsQuizUC.test.js.map +1 -1
  81. package/dist/cjs/Procedure/UCs/SetProcedureOrderMattersUC.js.map +1 -1
  82. package/dist/cjs/Procedure/UCs/SetProcedureOrderMattersUC.test.js.map +1 -1
  83. package/dist/cjs/Procedure/UCs/SetProcedureShowHintsUC.js.map +1 -1
  84. package/dist/cjs/Procedure/UCs/SetProcedureShowHintsUC.test.js.map +1 -1
  85. package/dist/cjs/Procedure/UCs/SubmitProcedureQuizUC.js.map +1 -1
  86. package/dist/cjs/Procedure/UCs/SubmitProcedureQuizUC.test.js.map +1 -1
  87. package/dist/cjs/Procedure/UCs/UpdateProcedureEventsUCHook.js.map +1 -1
  88. package/dist/cjs/Procedure/UCs/UpdateProcedureEventsUCHook.test.js.map +1 -1
  89. package/dist/cjs/Procedure/UCs/index.js.map +1 -1
  90. package/dist/cjs/Procedure/index.js.map +1 -1
  91. package/dist/cjs/Procedure/types.js.map +1 -1
  92. package/dist/cjs/RequestHandler/UC/SetThemeColorUC.test.js +9 -0
  93. package/dist/cjs/RequestHandler/UC/SetThemeColorUC.test.js.map +1 -1
  94. package/dist/cjs/ThemeColors/Entities/ThemeColors.js +24 -0
  95. package/dist/cjs/ThemeColors/Entities/ThemeColors.js.map +1 -1
  96. package/dist/cjs/ThemeColors/Entities/ThemeColors.test.js +20 -0
  97. package/dist/cjs/ThemeColors/Entities/ThemeColors.test.js.map +1 -1
  98. package/dist/cjs/TouchController/UC/UpdateTouchInoutBound.test.js.map +1 -1
  99. package/dist/cjs/TouchController/UC/UpdateTouchInputBound.js.map +1 -1
  100. package/dist/cjs/index.js.map +1 -1
  101. package/dist/esm/BaseApp/UC/RenderCanvasUC.js.map +1 -1
  102. package/dist/esm/BaseApp/UC/RenderCanvasUC.test.js.map +1 -1
  103. package/dist/esm/Challenge/Factories/ChallengeFeatureFactory.js.map +1 -1
  104. package/dist/esm/Challenge/Factories/ChallengeFeatureFactory.test.js.map +1 -1
  105. package/dist/esm/Dispatcher/Factories/DispatcherFeatureFactory.js +5 -4
  106. package/dist/esm/Dispatcher/Factories/DispatcherFeatureFactory.js.map +1 -1
  107. package/dist/esm/Dispatcher/Factories/DispatcherFeatureFactory.test.js +33 -0
  108. package/dist/esm/Dispatcher/Factories/DispatcherFeatureFactory.test.js.map +1 -0
  109. package/dist/esm/Dispatcher/Factories/setupDispatchers.js +2 -1
  110. package/dist/esm/Dispatcher/Factories/setupDispatchers.js.map +1 -1
  111. package/dist/esm/Dispatcher/Factories/setupDispatchers.test.js +31 -0
  112. package/dist/esm/Dispatcher/Factories/setupDispatchers.test.js.map +1 -0
  113. package/dist/esm/EventSystem/Entities/EventEntity.js.map +1 -1
  114. package/dist/esm/EventSystem/Entities/EventEntity.test.js +4 -1
  115. package/dist/esm/EventSystem/Entities/EventEntity.test.js.map +1 -1
  116. package/dist/esm/EventSystem/Entities/index.js.map +1 -1
  117. package/dist/esm/EventSystem/EventSystem.integration.test.js.map +1 -1
  118. package/dist/esm/EventSystem/Factories/EventSystemFeatureFactory.js.map +1 -1
  119. package/dist/esm/EventSystem/Factories/EventSystemFeatureFactory.test.js.map +1 -1
  120. package/dist/esm/EventSystem/Factories/index.js.map +1 -1
  121. package/dist/esm/EventSystem/Mocks/MockEventEntity.js.map +1 -1
  122. package/dist/esm/EventSystem/Mocks/index.js.map +1 -1
  123. package/dist/esm/EventSystem/index.js.map +1 -1
  124. package/dist/esm/EventSystem/types.js.map +1 -1
  125. package/dist/esm/LabelDrop/Factories/LabelDropFeatureFactory.js.map +1 -1
  126. package/dist/esm/LabelDrop/UseCases/SubmitLabelDropResultUC.js.map +1 -1
  127. package/dist/esm/LabelDrop/UseCases/SubmitLabelDropResultUC.test.js.map +1 -1
  128. package/dist/esm/LabelDrop/UseCases/index.js.map +1 -1
  129. package/dist/esm/Procedure/Adapters/index.js.map +1 -1
  130. package/dist/esm/Procedure/Adapters/procedureAdapter.js.map +1 -1
  131. package/dist/esm/Procedure/Adapters/procedureAdapter.test.js.map +1 -1
  132. package/dist/esm/Procedure/Adapters/procedureAuthoringAdapter.js.map +1 -1
  133. package/dist/esm/Procedure/Adapters/procedureAuthoringAdapter.test.js.map +1 -1
  134. package/dist/esm/Procedure/Adapters/procedureHintAdapter.js.map +1 -1
  135. package/dist/esm/Procedure/Adapters/procedureHintAdapter.test.js.map +1 -1
  136. package/dist/esm/Procedure/Adapters/procedureProgressAdapter.js.map +1 -1
  137. package/dist/esm/Procedure/Adapters/procedureProgressAdapter.test.js.map +1 -1
  138. package/dist/esm/Procedure/Adapters/procedureQuizResultAdapter.js.map +1 -1
  139. package/dist/esm/Procedure/Adapters/procedureQuizResultAdapter.test.js +3 -1
  140. package/dist/esm/Procedure/Adapters/procedureQuizResultAdapter.test.js.map +1 -1
  141. package/dist/esm/Procedure/Entities/HintRegistry.js.map +1 -1
  142. package/dist/esm/Procedure/Entities/HintRegistry.test.js.map +1 -1
  143. package/dist/esm/Procedure/Entities/ProcedureEntity.js.map +1 -1
  144. package/dist/esm/Procedure/Entities/ProcedureEntity.test.js +1 -12
  145. package/dist/esm/Procedure/Entities/ProcedureEntity.test.js.map +1 -1
  146. package/dist/esm/Procedure/Entities/index.js.map +1 -1
  147. package/dist/esm/Procedure/Factories/ProcedureFeatureFactory.js.map +1 -1
  148. package/dist/esm/Procedure/Factories/ProcedureFeatureFactory.test.js +5 -3
  149. package/dist/esm/Procedure/Factories/ProcedureFeatureFactory.test.js.map +1 -1
  150. package/dist/esm/Procedure/Factories/index.js.map +1 -1
  151. package/dist/esm/Procedure/Mocks/MockProcedureEntity.js.map +1 -1
  152. package/dist/esm/Procedure/Mocks/MockProcedurePM.js.map +1 -1
  153. package/dist/esm/Procedure/Mocks/index.js.map +1 -1
  154. package/dist/esm/Procedure/PM/ProcedurePM.js.map +1 -1
  155. package/dist/esm/Procedure/PM/ProcedurePM.test.js +2 -2
  156. package/dist/esm/Procedure/PM/ProcedurePM.test.js.map +1 -1
  157. package/dist/esm/Procedure/PM/index.js.map +1 -1
  158. package/dist/esm/Procedure/ProcedureEventSystem.integration.test.js +2 -2
  159. package/dist/esm/Procedure/ProcedureEventSystem.integration.test.js.map +1 -1
  160. package/dist/esm/Procedure/UCs/AddProcedureEventUC.js.map +1 -1
  161. package/dist/esm/Procedure/UCs/AddProcedureEventUC.test.js +3 -6
  162. package/dist/esm/Procedure/UCs/AddProcedureEventUC.test.js.map +1 -1
  163. package/dist/esm/Procedure/UCs/MoveProcedureEventDownUC.js.map +1 -1
  164. package/dist/esm/Procedure/UCs/MoveProcedureEventDownUC.test.js +2 -2
  165. package/dist/esm/Procedure/UCs/MoveProcedureEventDownUC.test.js.map +1 -1
  166. package/dist/esm/Procedure/UCs/MoveProcedureEventUpUC.js.map +1 -1
  167. package/dist/esm/Procedure/UCs/MoveProcedureEventUpUC.test.js +2 -2
  168. package/dist/esm/Procedure/UCs/MoveProcedureEventUpUC.test.js.map +1 -1
  169. package/dist/esm/Procedure/UCs/RecordProcedureEventUC.js.map +1 -1
  170. package/dist/esm/Procedure/UCs/RecordProcedureEventUC.test.js +2 -2
  171. package/dist/esm/Procedure/UCs/RecordProcedureEventUC.test.js.map +1 -1
  172. package/dist/esm/Procedure/UCs/RecordProcedureSessionUC.js.map +1 -1
  173. package/dist/esm/Procedure/UCs/RecordProcedureSessionUC.test.js +22 -4
  174. package/dist/esm/Procedure/UCs/RecordProcedureSessionUC.test.js.map +1 -1
  175. package/dist/esm/Procedure/UCs/RemoveProcedureEventUC.js.map +1 -1
  176. package/dist/esm/Procedure/UCs/RemoveProcedureEventUC.test.js +2 -2
  177. package/dist/esm/Procedure/UCs/RemoveProcedureEventUC.test.js.map +1 -1
  178. package/dist/esm/Procedure/UCs/ResetProcedureProgressUC.js.map +1 -1
  179. package/dist/esm/Procedure/UCs/ResetProcedureProgressUC.test.js +2 -2
  180. package/dist/esm/Procedure/UCs/ResetProcedureProgressUC.test.js.map +1 -1
  181. package/dist/esm/Procedure/UCs/SerializeProcedure.js.map +1 -1
  182. package/dist/esm/Procedure/UCs/SerializeProcedure.test.js +8 -3
  183. package/dist/esm/Procedure/UCs/SerializeProcedure.test.js.map +1 -1
  184. package/dist/esm/Procedure/UCs/SetProcedureIsQuizUC.js.map +1 -1
  185. package/dist/esm/Procedure/UCs/SetProcedureIsQuizUC.test.js +1 -1
  186. package/dist/esm/Procedure/UCs/SetProcedureIsQuizUC.test.js.map +1 -1
  187. package/dist/esm/Procedure/UCs/SetProcedureOrderMattersUC.js.map +1 -1
  188. package/dist/esm/Procedure/UCs/SetProcedureOrderMattersUC.test.js +1 -1
  189. package/dist/esm/Procedure/UCs/SetProcedureOrderMattersUC.test.js.map +1 -1
  190. package/dist/esm/Procedure/UCs/SetProcedureShowHintsUC.js.map +1 -1
  191. package/dist/esm/Procedure/UCs/SetProcedureShowHintsUC.test.js +1 -1
  192. package/dist/esm/Procedure/UCs/SetProcedureShowHintsUC.test.js.map +1 -1
  193. package/dist/esm/Procedure/UCs/SubmitProcedureQuizUC.js.map +1 -1
  194. package/dist/esm/Procedure/UCs/SubmitProcedureQuizUC.test.js +2 -2
  195. package/dist/esm/Procedure/UCs/SubmitProcedureQuizUC.test.js.map +1 -1
  196. package/dist/esm/Procedure/UCs/UpdateProcedureEventsUCHook.js.map +1 -1
  197. package/dist/esm/Procedure/UCs/UpdateProcedureEventsUCHook.test.js +1 -1
  198. package/dist/esm/Procedure/UCs/UpdateProcedureEventsUCHook.test.js.map +1 -1
  199. package/dist/esm/Procedure/UCs/index.js.map +1 -1
  200. package/dist/esm/Procedure/index.js.map +1 -1
  201. package/dist/esm/Procedure/types.js.map +1 -1
  202. package/dist/esm/RequestHandler/UC/SetThemeColorUC.test.js +9 -0
  203. package/dist/esm/RequestHandler/UC/SetThemeColorUC.test.js.map +1 -1
  204. package/dist/esm/ThemeColors/Entities/ThemeColors.js +24 -0
  205. package/dist/esm/ThemeColors/Entities/ThemeColors.js.map +1 -1
  206. package/dist/esm/ThemeColors/Entities/ThemeColors.test.js +20 -0
  207. package/dist/esm/ThemeColors/Entities/ThemeColors.test.js.map +1 -1
  208. package/dist/esm/TouchController/UC/UpdateTouchInoutBound.test.js.map +1 -1
  209. package/dist/esm/TouchController/UC/UpdateTouchInputBound.js.map +1 -1
  210. package/dist/esm/index.js.map +1 -1
  211. package/dist/types/Dispatcher/Factories/DispatcherFeatureFactory.d.ts +3 -3
  212. package/dist/types/Dispatcher/Factories/DispatcherFeatureFactory.d.ts.map +1 -1
  213. package/dist/types/Dispatcher/Factories/DispatcherFeatureFactory.test.d.ts +2 -0
  214. package/dist/types/Dispatcher/Factories/DispatcherFeatureFactory.test.d.ts.map +1 -0
  215. package/dist/types/Dispatcher/Factories/setupDispatchers.d.ts.map +1 -1
  216. package/dist/types/Dispatcher/Factories/setupDispatchers.test.d.ts +2 -0
  217. package/dist/types/Dispatcher/Factories/setupDispatchers.test.d.ts.map +1 -0
  218. package/dist/types/Procedure/Entities/ProcedureEntity.d.ts.map +1 -1
  219. package/dist/types/Procedure/Mocks/MockProcedureEntity.d.ts.map +1 -1
  220. package/dist/types/Procedure/UCs/AddProcedureEventUC.d.ts.map +1 -1
  221. package/dist/types/Procedure/UCs/RecordProcedureSessionUC.d.ts.map +1 -1
  222. package/dist/types/Procedure/UCs/SetProcedureIsQuizUC.d.ts.map +1 -1
  223. package/dist/types/Procedure/UCs/SubmitProcedureQuizUC.d.ts.map +1 -1
  224. package/dist/types/Procedure/types.d.ts.map +1 -1
  225. package/dist/types/ThemeColors/Entities/ThemeColors.d.ts +12 -0
  226. package/dist/types/ThemeColors/Entities/ThemeColors.d.ts.map +1 -1
  227. package/package.json +1 -1
  228. package/src/Dispatcher/README.md +9 -6
@@ -1 +1 @@
1
- {"version":3,"file":"procedureProgressAdapter.test.js","sourceRoot":"","sources":["../../../../src/Procedure/Adapters/procedureProgressAdapter.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { makeAppObjectRepo } from \"@vived/core\";\r\nimport { procedureProgressAdapter } from \"./procedureProgressAdapter\";\r\nimport { makeMockProcedurePM } from \"../Mocks/MockProcedurePM\";\r\n\r\nfunction makeTestRig() {\r\n\tconst appObjects = makeAppObjectRepo();\r\n\tconst mockPM = makeMockProcedurePM(appObjects);\r\n\treturn { appObjects, mockPM };\r\n}\r\n\r\ndescribe(\"procedureProgressAdapter\", () => {\r\n\tit(\"has the correct default VM shape\", () => {\r\n\t\tconst defaultVM = procedureProgressAdapter.defaultVM;\r\n\t\texpect(defaultVM.eventIds).toEqual([]);\r\n\t\texpect(defaultVM.availableEvents).toEqual([]);\r\n\t\texpect(defaultVM.userEventLog).toEqual([]);\r\n\t\texpect(defaultVM.currentStepIndex).toBe(0);\r\n\t\texpect(defaultVM.isComplete).toBe(false);\r\n\t\texpect(defaultVM.orderMatters).toBe(true);\r\n\t\texpect(defaultVM.progressPercentage).toBe(0);\r\n\t\texpect(defaultVM.isQuiz).toBe(false);\r\n\t\texpect(defaultVM.isSubmitted).toBe(false);\r\n\t\texpect(defaultVM.stepCategories).toEqual({});\r\n\t});\r\n\r\n\tit(\"calls addView on the PM when subscribing\", () => {\r\n\t\tconst { mockPM, appObjects } = makeTestRig();\r\n\t\tmockPM.addView = jest.fn();\r\n\t\tconst setVM = jest.fn();\r\n\r\n\t\tprocedureProgressAdapter.subscribe(appObjects, setVM);\r\n\r\n\t\texpect(mockPM.addView).toHaveBeenCalled();\r\n\t});\r\n\r\n\tit(\"calls removeView on the PM when unsubscribing\", () => {\r\n\t\tconst { mockPM, appObjects } = makeTestRig();\r\n\t\tmockPM.removeView = jest.fn();\r\n\t\tconst setVM = jest.fn();\r\n\r\n\t\tprocedureProgressAdapter.subscribe(appObjects, setVM);\r\n\t\tprocedureProgressAdapter.unsubscribe(appObjects, setVM);\r\n\r\n\t\texpect(mockPM.removeView).toHaveBeenCalled();\r\n\t});\r\n\r\n\tit(\"maps only progress fields from the full VM\", () => {\r\n\t\tconst { mockPM, appObjects } = makeTestRig();\r\n\t\tmockPM.addView = jest.fn();\r\n\t\tconst setVM = jest.fn();\r\n\r\n\t\tprocedureProgressAdapter.subscribe(appObjects, setVM);\r\n\r\n\t\tconst capturedWrapper = (mockPM.addView as jest.Mock).mock.calls[0][0];\r\n\t\tcapturedWrapper({\r\n\t\t\teventIds: [\"event_a\"],\r\n\t\t\tavailableEvents: [{ id: \"event_a\", name: \"Event A\" }],\r\n\t\t\tuserEventLog: [\"event_a\"],\r\n\t\t\tcurrentStepIndex: 1,\r\n\t\t\tisComplete: true,\r\n\t\t\torderMatters: false,\r\n\t\t\tprogressPercentage: 100,\r\n\t\t\tisQuiz: true,\r\n\t\t\tisSubmitted: true,\r\n\t\t\tvalidationMessage: null,\r\n\t\t\tnextExpectedEvent: null,\r\n\t\t\tauthoringValidationMessage: null,\r\n\t\t\tscore: null,\r\n\t\t\tshowHints: false,\r\n\t\t\tstepCategories: { event_a: \"assessed\" },\r\n\t\t});\r\n\r\n\t\texpect(setVM).toHaveBeenCalledWith({\r\n\t\t\teventIds: [\"event_a\"],\r\n\t\t\tavailableEvents: [{ id: \"event_a\", name: \"Event A\" }],\r\n\t\t\tuserEventLog: [\"event_a\"],\r\n\t\t\tcurrentStepIndex: 1,\r\n\t\t\tisComplete: true,\r\n\t\t\torderMatters: false,\r\n\t\t\tprogressPercentage: 100,\r\n\t\t\tisQuiz: true,\r\n\t\t\tisSubmitted: true,\r\n\t\t\tstepCategories: { event_a: \"assessed\" },\r\n\t\t});\r\n\t});\r\n});\r\n"]}
1
+ {"version":3,"file":"procedureProgressAdapter.test.js","sourceRoot":"","sources":["../../../../src/Procedure/Adapters/procedureProgressAdapter.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { makeAppObjectRepo } from \"@vived/core\";\nimport { procedureProgressAdapter } from \"./procedureProgressAdapter\";\nimport { makeMockProcedurePM } from \"../Mocks/MockProcedurePM\";\n\nfunction makeTestRig() {\n const appObjects = makeAppObjectRepo();\n const mockPM = makeMockProcedurePM(appObjects);\n return { appObjects, mockPM };\n}\n\ndescribe(\"procedureProgressAdapter\", () => {\n it(\"has the correct default VM shape\", () => {\n const defaultVM = procedureProgressAdapter.defaultVM;\n expect(defaultVM.eventIds).toEqual([]);\n expect(defaultVM.availableEvents).toEqual([]);\n expect(defaultVM.userEventLog).toEqual([]);\n expect(defaultVM.currentStepIndex).toBe(0);\n expect(defaultVM.isComplete).toBe(false);\n expect(defaultVM.orderMatters).toBe(true);\n expect(defaultVM.progressPercentage).toBe(0);\n expect(defaultVM.isQuiz).toBe(false);\n expect(defaultVM.isSubmitted).toBe(false);\n expect(defaultVM.stepCategories).toEqual({});\n });\n\n it(\"calls addView on the PM when subscribing\", () => {\n const { mockPM, appObjects } = makeTestRig();\n mockPM.addView = jest.fn();\n const setVM = jest.fn();\n\n procedureProgressAdapter.subscribe(appObjects, setVM);\n\n expect(mockPM.addView).toHaveBeenCalled();\n });\n\n it(\"calls removeView on the PM when unsubscribing\", () => {\n const { mockPM, appObjects } = makeTestRig();\n mockPM.removeView = jest.fn();\n const setVM = jest.fn();\n\n procedureProgressAdapter.subscribe(appObjects, setVM);\n procedureProgressAdapter.unsubscribe(appObjects, setVM);\n\n expect(mockPM.removeView).toHaveBeenCalled();\n });\n\n it(\"maps only progress fields from the full VM\", () => {\n const { mockPM, appObjects } = makeTestRig();\n mockPM.addView = jest.fn();\n const setVM = jest.fn();\n\n procedureProgressAdapter.subscribe(appObjects, setVM);\n\n const capturedWrapper = (mockPM.addView as jest.Mock).mock.calls[0][0];\n capturedWrapper({\n eventIds: [\"event_a\"],\n availableEvents: [{ id: \"event_a\", name: \"Event A\" }],\n userEventLog: [\"event_a\"],\n currentStepIndex: 1,\n isComplete: true,\n orderMatters: false,\n progressPercentage: 100,\n isQuiz: true,\n isSubmitted: true,\n validationMessage: null,\n nextExpectedEvent: null,\n authoringValidationMessage: null,\n score: null,\n showHints: false,\n stepCategories: { event_a: \"assessed\" },\n });\n\n expect(setVM).toHaveBeenCalledWith({\n eventIds: [\"event_a\"],\n availableEvents: [{ id: \"event_a\", name: \"Event A\" }],\n userEventLog: [\"event_a\"],\n currentStepIndex: 1,\n isComplete: true,\n orderMatters: false,\n progressPercentage: 100,\n isQuiz: true,\n isSubmitted: true,\n stepCategories: { event_a: \"assessed\" },\n });\n });\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"procedureQuizResultAdapter.js","sourceRoot":"","sources":["../../../../src/Procedure/Adapters/procedureQuizResultAdapter.ts"],"names":[],"mappings":";;;AACA,mDAAgD;AAGhD,SAAS,iBAAiB,CAAC,EAAe;IACxC,OAAO;QACL,UAAU,EAAE,EAAE,CAAC,UAAU;QACzB,MAAM,EAAE,EAAE,CAAC,MAAM;QACjB,kBAAkB,EAAE,EAAE,CAAC,kBAAkB;QACzC,QAAQ,EAAE,EAAE,CAAC,QAAQ;QACrB,eAAe,EAAE,EAAE,CAAC,eAAe;QACnC,YAAY,EAAE,EAAE,CAAC,YAAY;QAC7B,YAAY,EAAE,EAAE,CAAC,YAAY;QAC7B,KAAK,EAAE,EAAE,CAAC,KAAK;QACf,WAAW,EAAE,EAAE,CAAC,WAAW;QAC3B,cAAc,EAAE,EAAE,CAAC,cAAc;KAClC,CAAC;AACJ,CAAC;AAED,MAAM,0BAA0B;IAAhC;QAGE,cAAS,GAA0B;YACjC,UAAU,EAAE,KAAK;YACjB,MAAM,EAAE,KAAK;YACb,kBAAkB,EAAE,CAAC;YACrB,QAAQ,EAAE,EAAE;YACZ,eAAe,EAAE,EAAE;YACnB,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,EAAE;YAChB,KAAK,EAAE,IAAI;YACX,WAAW,EAAE,KAAK;YAClB,cAAc,EAAE,EAAE;SACnB,CAAC;QAEM,aAAQ,GAAG,IAAI,OAAO,EAG3B,CAAC;IA0BN,CAAC;IAxBC,SAAS,CACP,UAAyB,EACzB,KAA0C;QAE1C,MAAM,EAAE,GAAG,yBAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,MAAM,OAAO,GAAG,CAAC,EAAe,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAClC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACpB,IAAI,EAAE,CAAC,MAAM;YAAE,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,WAAW,CACT,UAAyB,EACzB,KAA0C;QAE1C,MAAM,EAAE,GAAG,yBAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,OAAO,EAAE,CAAC;YACZ,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACvB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;CACF;AAEY,QAAA,0BAA0B,GAAG,IAAI,0BAA0B,EAAE,CAAC","sourcesContent":["import { SingletonPmAdapter, AppObjectRepo } from \"@vived/core\";\r\nimport { ProcedurePM } from \"../PM/ProcedurePM\";\r\nimport { ProcedureQuizResultVM, ProcedureVM } from \"../types\";\r\n\r\nfunction mapToQuizResultVM(vm: ProcedureVM): ProcedureQuizResultVM {\r\n return {\r\n isComplete: vm.isComplete,\r\n isQuiz: vm.isQuiz,\r\n progressPercentage: vm.progressPercentage,\r\n eventIds: vm.eventIds,\r\n availableEvents: vm.availableEvents,\r\n orderMatters: vm.orderMatters,\r\n userEventLog: vm.userEventLog,\r\n score: vm.score,\r\n isSubmitted: vm.isSubmitted,\r\n stepCategories: vm.stepCategories,\r\n };\r\n}\r\n\r\nclass ProcedureQuizResultAdapter\r\n implements SingletonPmAdapter<ProcedureQuizResultVM>\r\n{\r\n defaultVM: ProcedureQuizResultVM = {\r\n isComplete: false,\r\n isQuiz: false,\r\n progressPercentage: 0,\r\n eventIds: [],\r\n availableEvents: [],\r\n orderMatters: true,\r\n userEventLog: [],\r\n score: null,\r\n isSubmitted: false,\r\n stepCategories: {},\r\n };\r\n\r\n private wrappers = new WeakMap<\r\n (vm: ProcedureQuizResultVM) => void,\r\n (vm: ProcedureVM) => void\r\n >();\r\n\r\n subscribe(\r\n appObjects: AppObjectRepo,\r\n setVM: (vm: ProcedureQuizResultVM) => void,\r\n ): void {\r\n const pm = ProcedurePM.get(appObjects);\r\n if (!pm) return;\r\n const wrapper = (vm: ProcedureVM) => setVM(mapToQuizResultVM(vm));\r\n this.wrappers.set(setVM, wrapper);\r\n pm.addView(wrapper);\r\n if (pm.lastVM) setVM(mapToQuizResultVM(pm.lastVM));\r\n }\r\n\r\n unsubscribe(\r\n appObjects: AppObjectRepo,\r\n setVM: (vm: ProcedureQuizResultVM) => void,\r\n ): void {\r\n const pm = ProcedurePM.get(appObjects);\r\n if (!pm) return;\r\n const wrapper = this.wrappers.get(setVM);\r\n if (wrapper) {\r\n pm.removeView(wrapper);\r\n this.wrappers.delete(setVM);\r\n }\r\n }\r\n}\r\n\r\nexport const procedureQuizResultAdapter = new ProcedureQuizResultAdapter();\r\n"]}
1
+ {"version":3,"file":"procedureQuizResultAdapter.js","sourceRoot":"","sources":["../../../../src/Procedure/Adapters/procedureQuizResultAdapter.ts"],"names":[],"mappings":";;;AACA,mDAAgD;AAGhD,SAAS,iBAAiB,CAAC,EAAe;IACxC,OAAO;QACL,UAAU,EAAE,EAAE,CAAC,UAAU;QACzB,MAAM,EAAE,EAAE,CAAC,MAAM;QACjB,kBAAkB,EAAE,EAAE,CAAC,kBAAkB;QACzC,QAAQ,EAAE,EAAE,CAAC,QAAQ;QACrB,eAAe,EAAE,EAAE,CAAC,eAAe;QACnC,YAAY,EAAE,EAAE,CAAC,YAAY;QAC7B,YAAY,EAAE,EAAE,CAAC,YAAY;QAC7B,KAAK,EAAE,EAAE,CAAC,KAAK;QACf,WAAW,EAAE,EAAE,CAAC,WAAW;QAC3B,cAAc,EAAE,EAAE,CAAC,cAAc;KAClC,CAAC;AACJ,CAAC;AAED,MAAM,0BAA0B;IAAhC;QAGE,cAAS,GAA0B;YACjC,UAAU,EAAE,KAAK;YACjB,MAAM,EAAE,KAAK;YACb,kBAAkB,EAAE,CAAC;YACrB,QAAQ,EAAE,EAAE;YACZ,eAAe,EAAE,EAAE;YACnB,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,EAAE;YAChB,KAAK,EAAE,IAAI;YACX,WAAW,EAAE,KAAK;YAClB,cAAc,EAAE,EAAE;SACnB,CAAC;QAEM,aAAQ,GAAG,IAAI,OAAO,EAG3B,CAAC;IA0BN,CAAC;IAxBC,SAAS,CACP,UAAyB,EACzB,KAA0C;QAE1C,MAAM,EAAE,GAAG,yBAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,MAAM,OAAO,GAAG,CAAC,EAAe,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAClC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACpB,IAAI,EAAE,CAAC,MAAM;YAAE,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,WAAW,CACT,UAAyB,EACzB,KAA0C;QAE1C,MAAM,EAAE,GAAG,yBAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,OAAO,EAAE,CAAC;YACZ,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACvB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;CACF;AAEY,QAAA,0BAA0B,GAAG,IAAI,0BAA0B,EAAE,CAAC","sourcesContent":["import { SingletonPmAdapter, AppObjectRepo } from \"@vived/core\";\nimport { ProcedurePM } from \"../PM/ProcedurePM\";\nimport { ProcedureQuizResultVM, ProcedureVM } from \"../types\";\n\nfunction mapToQuizResultVM(vm: ProcedureVM): ProcedureQuizResultVM {\n return {\n isComplete: vm.isComplete,\n isQuiz: vm.isQuiz,\n progressPercentage: vm.progressPercentage,\n eventIds: vm.eventIds,\n availableEvents: vm.availableEvents,\n orderMatters: vm.orderMatters,\n userEventLog: vm.userEventLog,\n score: vm.score,\n isSubmitted: vm.isSubmitted,\n stepCategories: vm.stepCategories,\n };\n}\n\nclass ProcedureQuizResultAdapter\n implements SingletonPmAdapter<ProcedureQuizResultVM>\n{\n defaultVM: ProcedureQuizResultVM = {\n isComplete: false,\n isQuiz: false,\n progressPercentage: 0,\n eventIds: [],\n availableEvents: [],\n orderMatters: true,\n userEventLog: [],\n score: null,\n isSubmitted: false,\n stepCategories: {},\n };\n\n private wrappers = new WeakMap<\n (vm: ProcedureQuizResultVM) => void,\n (vm: ProcedureVM) => void\n >();\n\n subscribe(\n appObjects: AppObjectRepo,\n setVM: (vm: ProcedureQuizResultVM) => void,\n ): void {\n const pm = ProcedurePM.get(appObjects);\n if (!pm) return;\n const wrapper = (vm: ProcedureVM) => setVM(mapToQuizResultVM(vm));\n this.wrappers.set(setVM, wrapper);\n pm.addView(wrapper);\n if (pm.lastVM) setVM(mapToQuizResultVM(pm.lastVM));\n }\n\n unsubscribe(\n appObjects: AppObjectRepo,\n setVM: (vm: ProcedureQuizResultVM) => void,\n ): void {\n const pm = ProcedurePM.get(appObjects);\n if (!pm) return;\n const wrapper = this.wrappers.get(setVM);\n if (wrapper) {\n pm.removeView(wrapper);\n this.wrappers.delete(setVM);\n }\n }\n}\n\nexport const procedureQuizResultAdapter = new ProcedureQuizResultAdapter();\n"]}
@@ -44,7 +44,9 @@ describe("procedureQuizResultAdapter", () => {
44
44
  procedureQuizResultAdapter_1.procedureQuizResultAdapter.subscribe(appObjects, setVM);
45
45
  const score = {
46
46
  percentage: 75,
47
- comparison: [{ eventId: "event_a", expected: true, actual: true, correct: true }],
47
+ comparison: [
48
+ { eventId: "event_a", expected: true, actual: true, correct: true },
49
+ ],
48
50
  };
49
51
  const capturedWrapper = mockPM.addView.mock.calls[0][0];
50
52
  capturedWrapper({
@@ -1 +1 @@
1
- {"version":3,"file":"procedureQuizResultAdapter.test.js","sourceRoot":"","sources":["../../../../src/Procedure/Adapters/procedureQuizResultAdapter.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { makeAppObjectRepo } from \"@vived/core\";\r\nimport { procedureQuizResultAdapter } from \"./procedureQuizResultAdapter\";\r\nimport { makeMockProcedurePM } from \"../Mocks/MockProcedurePM\";\r\n\r\nfunction makeTestRig() {\r\n\tconst appObjects = makeAppObjectRepo();\r\n\tconst mockPM = makeMockProcedurePM(appObjects);\r\n\treturn { appObjects, mockPM };\r\n}\r\n\r\ndescribe(\"procedureQuizResultAdapter\", () => {\r\n\tit(\"has the correct default VM shape\", () => {\r\n\t\tconst defaultVM = procedureQuizResultAdapter.defaultVM;\r\n\t\texpect(defaultVM.isComplete).toBe(false);\r\n\t\texpect(defaultVM.isQuiz).toBe(false);\r\n\t\texpect(defaultVM.progressPercentage).toBe(0);\r\n\t\texpect(defaultVM.eventIds).toEqual([]);\r\n\t\texpect(defaultVM.availableEvents).toEqual([]);\r\n\t\texpect(defaultVM.orderMatters).toBe(true);\r\n\t\texpect(defaultVM.userEventLog).toEqual([]);\r\n\t\texpect(defaultVM.score).toBeNull();\r\n\t\texpect(defaultVM.isSubmitted).toBe(false);\r\n\t\texpect(defaultVM.stepCategories).toEqual({});\r\n\t});\r\n\r\n\tit(\"calls addView on the PM when subscribing\", () => {\r\n\t\tconst { mockPM, appObjects } = makeTestRig();\r\n\t\tmockPM.addView = jest.fn();\r\n\t\tconst setVM = jest.fn();\r\n\r\n\t\tprocedureQuizResultAdapter.subscribe(appObjects, setVM);\r\n\r\n\t\texpect(mockPM.addView).toHaveBeenCalled();\r\n\t});\r\n\r\n\tit(\"calls removeView on the PM when unsubscribing\", () => {\r\n\t\tconst { mockPM, appObjects } = makeTestRig();\r\n\t\tmockPM.removeView = jest.fn();\r\n\t\tconst setVM = jest.fn();\r\n\r\n\t\tprocedureQuizResultAdapter.subscribe(appObjects, setVM);\r\n\t\tprocedureQuizResultAdapter.unsubscribe(appObjects, setVM);\r\n\r\n\t\texpect(mockPM.removeView).toHaveBeenCalled();\r\n\t});\r\n\r\n\tit(\"maps only quiz result fields from the full VM\", () => {\r\n\t\tconst { mockPM, appObjects } = makeTestRig();\r\n\t\tmockPM.addView = jest.fn();\r\n\t\tconst setVM = jest.fn();\r\n\r\n\t\tprocedureQuizResultAdapter.subscribe(appObjects, setVM);\r\n\r\n\t\tconst score = {\r\n\t\t\tpercentage: 75,\r\n\t\t\tcomparison: [{ eventId: \"event_a\", expected: true, actual: true, correct: true }],\r\n\t\t};\r\n\r\n\t\tconst capturedWrapper = (mockPM.addView as jest.Mock).mock.calls[0][0];\r\n\t\tcapturedWrapper({\r\n\t\t\tisComplete: true,\r\n\t\t\tisQuiz: true,\r\n\t\t\tprogressPercentage: 75,\r\n\t\t\teventIds: [\"event_a\"],\r\n\t\t\tavailableEvents: [{ id: \"event_a\", name: \"Event A\" }],\r\n\t\t\torderMatters: false,\r\n\t\t\tuserEventLog: [\"event_a\"],\r\n\t\t\tscore,\r\n\t\t\tisSubmitted: true,\r\n\t\t\tvalidationMessage: null,\r\n\t\t\tnextExpectedEvent: null,\r\n\t\t\tauthoringValidationMessage: null,\r\n\t\t\tcurrentStepIndex: 1,\r\n\t\t\tshowHints: false,\r\n\t\t\tstepCategories: { event_a: \"assessed\" },\r\n\t\t});\r\n\r\n\t\texpect(setVM).toHaveBeenCalledWith({\r\n\t\t\tisComplete: true,\r\n\t\t\tisQuiz: true,\r\n\t\t\tprogressPercentage: 75,\r\n\t\t\teventIds: [\"event_a\"],\r\n\t\t\tavailableEvents: [{ id: \"event_a\", name: \"Event A\" }],\r\n\t\t\torderMatters: false,\r\n\t\t\tuserEventLog: [\"event_a\"],\r\n\t\t\tscore,\r\n\t\t\tisSubmitted: true,\r\n\t\t\tstepCategories: { event_a: \"assessed\" },\r\n\t\t});\r\n\t});\r\n});\r\n"]}
1
+ {"version":3,"file":"procedureQuizResultAdapter.test.js","sourceRoot":"","sources":["../../../../src/Procedure/Adapters/procedureQuizResultAdapter.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { makeAppObjectRepo } from \"@vived/core\";\nimport { procedureQuizResultAdapter } from \"./procedureQuizResultAdapter\";\nimport { makeMockProcedurePM } from \"../Mocks/MockProcedurePM\";\n\nfunction makeTestRig() {\n const appObjects = makeAppObjectRepo();\n const mockPM = makeMockProcedurePM(appObjects);\n return { appObjects, mockPM };\n}\n\ndescribe(\"procedureQuizResultAdapter\", () => {\n it(\"has the correct default VM shape\", () => {\n const defaultVM = procedureQuizResultAdapter.defaultVM;\n expect(defaultVM.isComplete).toBe(false);\n expect(defaultVM.isQuiz).toBe(false);\n expect(defaultVM.progressPercentage).toBe(0);\n expect(defaultVM.eventIds).toEqual([]);\n expect(defaultVM.availableEvents).toEqual([]);\n expect(defaultVM.orderMatters).toBe(true);\n expect(defaultVM.userEventLog).toEqual([]);\n expect(defaultVM.score).toBeNull();\n expect(defaultVM.isSubmitted).toBe(false);\n expect(defaultVM.stepCategories).toEqual({});\n });\n\n it(\"calls addView on the PM when subscribing\", () => {\n const { mockPM, appObjects } = makeTestRig();\n mockPM.addView = jest.fn();\n const setVM = jest.fn();\n\n procedureQuizResultAdapter.subscribe(appObjects, setVM);\n\n expect(mockPM.addView).toHaveBeenCalled();\n });\n\n it(\"calls removeView on the PM when unsubscribing\", () => {\n const { mockPM, appObjects } = makeTestRig();\n mockPM.removeView = jest.fn();\n const setVM = jest.fn();\n\n procedureQuizResultAdapter.subscribe(appObjects, setVM);\n procedureQuizResultAdapter.unsubscribe(appObjects, setVM);\n\n expect(mockPM.removeView).toHaveBeenCalled();\n });\n\n it(\"maps only quiz result fields from the full VM\", () => {\n const { mockPM, appObjects } = makeTestRig();\n mockPM.addView = jest.fn();\n const setVM = jest.fn();\n\n procedureQuizResultAdapter.subscribe(appObjects, setVM);\n\n const score = {\n percentage: 75,\n comparison: [\n { eventId: \"event_a\", expected: true, actual: true, correct: true },\n ],\n };\n\n const capturedWrapper = (mockPM.addView as jest.Mock).mock.calls[0][0];\n capturedWrapper({\n isComplete: true,\n isQuiz: true,\n progressPercentage: 75,\n eventIds: [\"event_a\"],\n availableEvents: [{ id: \"event_a\", name: \"Event A\" }],\n orderMatters: false,\n userEventLog: [\"event_a\"],\n score,\n isSubmitted: true,\n validationMessage: null,\n nextExpectedEvent: null,\n authoringValidationMessage: null,\n currentStepIndex: 1,\n showHints: false,\n stepCategories: { event_a: \"assessed\" },\n });\n\n expect(setVM).toHaveBeenCalledWith({\n isComplete: true,\n isQuiz: true,\n progressPercentage: 75,\n eventIds: [\"event_a\"],\n availableEvents: [{ id: \"event_a\", name: \"Event A\" }],\n orderMatters: false,\n userEventLog: [\"event_a\"],\n score,\n isSubmitted: true,\n stepCategories: { event_a: \"assessed\" },\n });\n });\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"HintRegistry.js","sourceRoot":"","sources":["../../../../src/Procedure/Entities/HintRegistry.ts"],"names":[],"mappings":";;;AAwBA,4CAEC;AA1BD,sCAKqB;AAErB;;;;;GAKG;AACH,MAAsB,YAAa,SAAQ,sBAAe;;AAA1D,oCASC;AARiB,iBAAI,GAAG,cAAc,CAAC;AAM/B,gBAAG,GAAG,CAAC,UAAyB,EAA4B,EAAE,CACnE,IAAA,4BAAqB,EAAC,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAGzD,SAAgB,gBAAgB,CAAC,SAAoB;IACnD,OAAO,IAAI,eAAe,CAAC,SAAS,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,eAAgB,SAAQ,YAAY;IAGxC,QAAQ,CAAC,WAAmB,EAAE,QAAkB;QAC9C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAED,oBAAoB,CAAC,OAAe;QAClC,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,YAAY,SAAoB;QAC9B,KAAK,CAAC,SAAS,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QAnB9B,qBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;QAoBnD,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;CACF","sourcesContent":["import {\r\n AppObject,\r\n AppObjectEntity,\r\n AppObjectRepo,\r\n getSingletonComponent,\r\n} from \"@vived/core\";\r\n\r\n/**\r\n * HintRegistry is a domain-level singleton that stores event-to-appObject\r\n * mappings for the procedure hint system. It is framework-agnostic (no Mesh\r\n * references) and serves as the source of truth for which interactive object\r\n * is associated with which event IDs.\r\n */\r\nexport abstract class HintRegistry extends AppObjectEntity {\r\n static readonly type = \"HintRegistry\";\r\n\r\n abstract register(appObjectId: string, eventIds: string[]): void;\r\n abstract getAppObjectForEvent(eventId: string): string | undefined;\r\n abstract getAllMappings(): ReadonlyMap<string, string>;\r\n\r\n static get = (appObjects: AppObjectRepo): HintRegistry | undefined =>\r\n getSingletonComponent(HintRegistry.type, appObjects);\r\n}\r\n\r\nexport function makeHintRegistry(appObject: AppObject): HintRegistry {\r\n return new HintRegistryImp(appObject);\r\n}\r\n\r\nclass HintRegistryImp extends HintRegistry {\r\n private eventToAppObject = new Map<string, string>();\r\n\r\n register(appObjectId: string, eventIds: string[]): void {\r\n for (const eventId of eventIds) {\r\n if (!this.eventToAppObject.has(eventId)) {\r\n this.eventToAppObject.set(eventId, appObjectId);\r\n }\r\n }\r\n }\r\n\r\n getAppObjectForEvent(eventId: string): string | undefined {\r\n return this.eventToAppObject.get(eventId);\r\n }\r\n\r\n getAllMappings(): ReadonlyMap<string, string> {\r\n return this.eventToAppObject;\r\n }\r\n\r\n constructor(appObject: AppObject) {\r\n super(appObject, HintRegistry.type);\r\n this.appObjects.registerSingleton(this);\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"HintRegistry.js","sourceRoot":"","sources":["../../../../src/Procedure/Entities/HintRegistry.ts"],"names":[],"mappings":";;;AAwBA,4CAEC;AA1BD,sCAKqB;AAErB;;;;;GAKG;AACH,MAAsB,YAAa,SAAQ,sBAAe;;AAA1D,oCASC;AARiB,iBAAI,GAAG,cAAc,CAAC;AAM/B,gBAAG,GAAG,CAAC,UAAyB,EAA4B,EAAE,CACnE,IAAA,4BAAqB,EAAC,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAGzD,SAAgB,gBAAgB,CAAC,SAAoB;IACnD,OAAO,IAAI,eAAe,CAAC,SAAS,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,eAAgB,SAAQ,YAAY;IAGxC,QAAQ,CAAC,WAAmB,EAAE,QAAkB;QAC9C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAED,oBAAoB,CAAC,OAAe;QAClC,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,YAAY,SAAoB;QAC9B,KAAK,CAAC,SAAS,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QAnB9B,qBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;QAoBnD,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;CACF","sourcesContent":["import {\n AppObject,\n AppObjectEntity,\n AppObjectRepo,\n getSingletonComponent,\n} from \"@vived/core\";\n\n/**\n * HintRegistry is a domain-level singleton that stores event-to-appObject\n * mappings for the procedure hint system. It is framework-agnostic (no Mesh\n * references) and serves as the source of truth for which interactive object\n * is associated with which event IDs.\n */\nexport abstract class HintRegistry extends AppObjectEntity {\n static readonly type = \"HintRegistry\";\n\n abstract register(appObjectId: string, eventIds: string[]): void;\n abstract getAppObjectForEvent(eventId: string): string | undefined;\n abstract getAllMappings(): ReadonlyMap<string, string>;\n\n static get = (appObjects: AppObjectRepo): HintRegistry | undefined =>\n getSingletonComponent(HintRegistry.type, appObjects);\n}\n\nexport function makeHintRegistry(appObject: AppObject): HintRegistry {\n return new HintRegistryImp(appObject);\n}\n\nclass HintRegistryImp extends HintRegistry {\n private eventToAppObject = new Map<string, string>();\n\n register(appObjectId: string, eventIds: string[]): void {\n for (const eventId of eventIds) {\n if (!this.eventToAppObject.has(eventId)) {\n this.eventToAppObject.set(eventId, appObjectId);\n }\n }\n }\n\n getAppObjectForEvent(eventId: string): string | undefined {\n return this.eventToAppObject.get(eventId);\n }\n\n getAllMappings(): ReadonlyMap<string, string> {\n return this.eventToAppObject;\n }\n\n constructor(appObject: AppObject) {\n super(appObject, HintRegistry.type);\n this.appObjects.registerSingleton(this);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"HintRegistry.test.js","sourceRoot":"","sources":["../../../../src/Procedure/Entities/HintRegistry.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { makeAppObjectRepo } from \"@vived/core\";\r\nimport { HintRegistry, makeHintRegistry } from \"./HintRegistry\";\r\n\r\nfunction makeTestRig() {\r\n\tconst appObjects = makeAppObjectRepo();\r\n\tconst registerSingletonSpy = jest.spyOn(appObjects, \"registerSingleton\");\r\n\tconst appObject = appObjects.getOrCreate(\"Procedure\");\r\n\tconst registry = makeHintRegistry(appObject);\r\n\treturn { appObjects, appObject, registry, registerSingletonSpy };\r\n}\r\n\r\ndescribe(\"HintRegistry\", () => {\r\n\tit(\"registers itself as a singleton\", () => {\r\n\t\tconst { registerSingletonSpy, registry } = makeTestRig();\r\n\t\texpect(registerSingletonSpy).toHaveBeenCalledWith(registry);\r\n\t});\r\n\r\n\tit(\"can be retrieved via static get method\", () => {\r\n\t\tconst { appObjects, registry } = makeTestRig();\r\n\t\texpect(HintRegistry.get(appObjects)).toBe(registry);\r\n\t});\r\n\r\n\tit(\"registers an appObject for a single event ID\", () => {\r\n\t\tconst { registry } = makeTestRig();\r\n\t\tregistry.register(\"obj-1\", [\"event_a\"]);\r\n\t\texpect(registry.getAppObjectForEvent(\"event_a\")).toBe(\"obj-1\");\r\n\t});\r\n\r\n\tit(\"registers an appObject for multiple event IDs\", () => {\r\n\t\tconst { registry } = makeTestRig();\r\n\t\tregistry.register(\"obj-1\", [\"event_a\", \"event_b\", \"event_c\"]);\r\n\t\texpect(registry.getAppObjectForEvent(\"event_a\")).toBe(\"obj-1\");\r\n\t\texpect(registry.getAppObjectForEvent(\"event_b\")).toBe(\"obj-1\");\r\n\t\texpect(registry.getAppObjectForEvent(\"event_c\")).toBe(\"obj-1\");\r\n\t});\r\n\r\n\tit(\"returns undefined for unregistered event IDs\", () => {\r\n\t\tconst { registry } = makeTestRig();\r\n\t\texpect(registry.getAppObjectForEvent(\"unknown_event\")).toBeUndefined();\r\n\t});\r\n\r\n\tit(\"first registration wins for duplicate event IDs\", () => {\r\n\t\tconst { registry } = makeTestRig();\r\n\t\tregistry.register(\"obj-1\", [\"shared_event\"]);\r\n\t\tregistry.register(\"obj-2\", [\"shared_event\"]);\r\n\t\texpect(registry.getAppObjectForEvent(\"shared_event\")).toBe(\"obj-1\");\r\n\t});\r\n\r\n\tit(\"supports multiple appObjects with different event IDs\", () => {\r\n\t\tconst { registry } = makeTestRig();\r\n\t\tregistry.register(\"obj-1\", [\"event_a\", \"event_b\"]);\r\n\t\tregistry.register(\"obj-2\", [\"event_c\", \"event_d\"]);\r\n\t\texpect(registry.getAppObjectForEvent(\"event_a\")).toBe(\"obj-1\");\r\n\t\texpect(registry.getAppObjectForEvent(\"event_c\")).toBe(\"obj-2\");\r\n\t});\r\n\r\n\tit(\"getAllMappings returns all registered event-to-appObject pairs\", () => {\r\n\t\tconst { registry } = makeTestRig();\r\n\t\tregistry.register(\"obj-1\", [\"event_a\", \"event_b\"]);\r\n\t\tregistry.register(\"obj-2\", [\"event_c\"]);\r\n\r\n\t\tconst mappings = registry.getAllMappings();\r\n\t\texpect(mappings.size).toBe(3);\r\n\t\texpect(mappings.get(\"event_a\")).toBe(\"obj-1\");\r\n\t\texpect(mappings.get(\"event_b\")).toBe(\"obj-1\");\r\n\t\texpect(mappings.get(\"event_c\")).toBe(\"obj-2\");\r\n\t});\r\n\r\n\tit(\"getAllMappings returns empty map when nothing is registered\", () => {\r\n\t\tconst { registry } = makeTestRig();\r\n\t\texpect(registry.getAllMappings().size).toBe(0);\r\n\t});\r\n});\r\n"]}
1
+ {"version":3,"file":"HintRegistry.test.js","sourceRoot":"","sources":["../../../../src/Procedure/Entities/HintRegistry.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { makeAppObjectRepo } from \"@vived/core\";\nimport { HintRegistry, makeHintRegistry } from \"./HintRegistry\";\n\nfunction makeTestRig() {\n const appObjects = makeAppObjectRepo();\n const registerSingletonSpy = jest.spyOn(appObjects, \"registerSingleton\");\n const appObject = appObjects.getOrCreate(\"Procedure\");\n const registry = makeHintRegistry(appObject);\n return { appObjects, appObject, registry, registerSingletonSpy };\n}\n\ndescribe(\"HintRegistry\", () => {\n it(\"registers itself as a singleton\", () => {\n const { registerSingletonSpy, registry } = makeTestRig();\n expect(registerSingletonSpy).toHaveBeenCalledWith(registry);\n });\n\n it(\"can be retrieved via static get method\", () => {\n const { appObjects, registry } = makeTestRig();\n expect(HintRegistry.get(appObjects)).toBe(registry);\n });\n\n it(\"registers an appObject for a single event ID\", () => {\n const { registry } = makeTestRig();\n registry.register(\"obj-1\", [\"event_a\"]);\n expect(registry.getAppObjectForEvent(\"event_a\")).toBe(\"obj-1\");\n });\n\n it(\"registers an appObject for multiple event IDs\", () => {\n const { registry } = makeTestRig();\n registry.register(\"obj-1\", [\"event_a\", \"event_b\", \"event_c\"]);\n expect(registry.getAppObjectForEvent(\"event_a\")).toBe(\"obj-1\");\n expect(registry.getAppObjectForEvent(\"event_b\")).toBe(\"obj-1\");\n expect(registry.getAppObjectForEvent(\"event_c\")).toBe(\"obj-1\");\n });\n\n it(\"returns undefined for unregistered event IDs\", () => {\n const { registry } = makeTestRig();\n expect(registry.getAppObjectForEvent(\"unknown_event\")).toBeUndefined();\n });\n\n it(\"first registration wins for duplicate event IDs\", () => {\n const { registry } = makeTestRig();\n registry.register(\"obj-1\", [\"shared_event\"]);\n registry.register(\"obj-2\", [\"shared_event\"]);\n expect(registry.getAppObjectForEvent(\"shared_event\")).toBe(\"obj-1\");\n });\n\n it(\"supports multiple appObjects with different event IDs\", () => {\n const { registry } = makeTestRig();\n registry.register(\"obj-1\", [\"event_a\", \"event_b\"]);\n registry.register(\"obj-2\", [\"event_c\", \"event_d\"]);\n expect(registry.getAppObjectForEvent(\"event_a\")).toBe(\"obj-1\");\n expect(registry.getAppObjectForEvent(\"event_c\")).toBe(\"obj-2\");\n });\n\n it(\"getAllMappings returns all registered event-to-appObject pairs\", () => {\n const { registry } = makeTestRig();\n registry.register(\"obj-1\", [\"event_a\", \"event_b\"]);\n registry.register(\"obj-2\", [\"event_c\"]);\n\n const mappings = registry.getAllMappings();\n expect(mappings.size).toBe(3);\n expect(mappings.get(\"event_a\")).toBe(\"obj-1\");\n expect(mappings.get(\"event_b\")).toBe(\"obj-1\");\n expect(mappings.get(\"event_c\")).toBe(\"obj-2\");\n });\n\n it(\"getAllMappings returns empty map when nothing is registered\", () => {\n const { registry } = makeTestRig();\n expect(registry.getAllMappings().size).toBe(0);\n });\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ProcedureEntity.js","sourceRoot":"","sources":["../../../../src/Procedure/Entities/ProcedureEntity.ts"],"names":[],"mappings":"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","sourcesContent":["import {\r\n AppObject,\r\n AppObjectEntity,\r\n AppObjectRepo,\r\n getSingletonComponent,\r\n MemoizedString,\r\n} from \"@vived/core\";\r\nimport { Challenge } from \"../../Challenge\";\r\nimport { EventCategory } from \"../../EventSystem/types\";\r\nimport { EventCategoryLookup } from \"../types\";\r\n\r\nexport abstract class ProcedureEntity\r\n extends AppObjectEntity\r\n implements Challenge\r\n{\r\n static readonly type = \"ProcedureEntity\";\r\n\r\n readonly challengeID = \"PROCEDURE\";\r\n name = \"Procedure\";\r\n abstract get helpHeading(): string;\r\n abstract get consumerHelpText(): string;\r\n authorHelpText =\r\n \"Create step-by-step procedures by selecting events that users must emit.\";\r\n\r\n abstract get eventIds(): string[];\r\n abstract get orderMatters(): boolean;\r\n abstract get showHints(): boolean;\r\n abstract get isQuiz(): boolean;\r\n abstract get userEventLog(): string[];\r\n abstract get currentStepIndex(): number;\r\n abstract get isComplete(): boolean;\r\n abstract get validationMessage(): string | null;\r\n abstract get score(): {\r\n percentage: number;\r\n comparison: {eventId: string; expected: boolean; actual: boolean; correct: boolean}[];\r\n } | null;\r\n abstract get isSubmitted(): boolean;\r\n\r\n abstract addEventId(eventId: string): void;\r\n abstract removeEventId(eventId: string): void;\r\n abstract clearEventIds(): void;\r\n abstract recordUserEvent(eventId: string): void;\r\n abstract validateProgress(): string | null;\r\n abstract getNextExpectedEvent(): string | null;\r\n abstract reset(): void;\r\n abstract moveEventUp(index: number): void;\r\n abstract moveEventDown(index: number): void;\r\n abstract getAuthoringValidationMessage(): string | null;\r\n\r\n abstract setOrderMatters(orderMatters: boolean): void;\r\n abstract setShowHints(showHints: boolean): void;\r\n abstract setIsQuiz(isQuiz: boolean): void;\r\n\r\n abstract get isRecording(): boolean;\r\n abstract setIsRecording(value: boolean): void;\r\n\r\n /**\r\n * Inject the Registry lookup used to classify steps (#53). Wired by the\r\n * FeatureFactory; evaluated at call time so late registrations are seen.\r\n * With no lookup injected every step is \"assessed\".\r\n */\r\n abstract setEventCategoryLookup(lookup: EventCategoryLookup): void;\r\n /** The category of an authored (or any) event id, via the injected lookup. */\r\n abstract getEventCategory(eventId: string): EventCategory;\r\n\r\n abstract getProgressPercentage(): number;\r\n abstract calculateScore(): {\r\n percentage: number;\r\n comparison: {eventId: string; expected: boolean; actual: boolean; correct: boolean}[];\r\n };\r\n abstract submit(): void;\r\n\r\n static get = (appObjects: AppObjectRepo): ProcedureEntity | undefined =>\r\n getSingletonComponent(ProcedureEntity.type, appObjects);\r\n}\r\n\r\nexport function makeProcedureEntity(appObject: AppObject): ProcedureEntity {\r\n return new ProcedureEntityImp(appObject);\r\n}\r\n\r\n/**\r\n * Aligns `actual` against `expected` by longest common subsequence (LCS) and\r\n * reports, for each index of `expected`, whether that step takes part in the\r\n * alignment. `matched.filter(Boolean).length` is the LCS length.\r\n *\r\n * Pure function over two plain arrays: callers decide what goes in. That is the\r\n * seam for event categories (#53) — pre-filter both arrays to the assessed\r\n * subsequence and nothing in here needs to change.\r\n *\r\n * Deterministic tie-break: when several alignments share the maximum length\r\n * (e.g. two swapped steps), the one that matches the EARLIEST expected steps\r\n * wins, so the same step is reported incorrect on every run.\r\n *\r\n * O(n·m) dynamic programming; procedures are ~20 steps at most.\r\n */\r\nfunction alignBySubsequence(\r\n expected: string[],\r\n actual: string[],\r\n): boolean[] {\r\n const n = expected.length;\r\n const m = actual.length;\r\n\r\n // lcs[i][j] = LCS length of expected[i..] against actual[j..]\r\n const lcs: number[][] = Array.from({ length: n + 1 }, () =>\r\n new Array<number>(m + 1).fill(0),\r\n );\r\n for (let i = n - 1; i >= 0; i--) {\r\n for (let j = m - 1; j >= 0; j--) {\r\n lcs[i][j] =\r\n expected[i] === actual[j]\r\n ? lcs[i + 1][j + 1] + 1\r\n : Math.max(lcs[i + 1][j], lcs[i][j + 1]);\r\n }\r\n }\r\n\r\n // Walk forward from the start. Matching an equal pair is always optimal.\r\n // On a mismatch, prefer skipping the actual entry whenever that costs\r\n // nothing, which keeps the current (earliest) expected step in play.\r\n const matched = new Array<boolean>(n).fill(false);\r\n let e = 0; // index into expected\r\n let a = 0; // index into actual\r\n while (e < n && a < m) {\r\n if (expected[e] === actual[a]) {\r\n matched[e] = true;\r\n e++;\r\n a++;\r\n } else if (lcs[e][a + 1] === lcs[e][a]) {\r\n a++;\r\n } else {\r\n e++;\r\n }\r\n }\r\n return matched;\r\n}\r\n\r\nclass ProcedureEntityImp extends ProcedureEntity {\r\n private _eventIds: string[] = [];\r\n private _orderMatters = true;\r\n private _showHints = true;\r\n private _isQuiz = false;\r\n private _isRecording = false;\r\n private _userEventLog: string[] = [];\r\n private _currentStepIndex = 0;\r\n private _validationMessage: string | null = null;\r\n private _score: {\r\n percentage: number;\r\n comparison: {eventId: string; expected: boolean; actual: boolean; correct: boolean}[];\r\n } | null = null;\r\n private _isSubmitted = false;\r\n private _getEventCategory: EventCategoryLookup = () => \"assessed\";\r\n\r\n get helpHeading(): string {\r\n if (this._isQuiz) return \"Procedure Challenge\";\r\n else return \"Procedure Training\";\r\n }\r\n\r\n get consumerHelpText(): string {\r\n if (this._isQuiz)\r\n return \"Complete the procedure challenge on your own and get scored after submitting.\";\r\n else return \"Follow the steps in order to complete the training procedure.\";\r\n }\r\n\r\n private memoizedState = new MemoizedString(\"\", this.notifyOnChange);\r\n\r\n get eventIds(): string[] {\r\n return [...this._eventIds];\r\n }\r\n\r\n get orderMatters(): boolean {\r\n return this._orderMatters;\r\n }\r\n\r\n get showHints(): boolean {\r\n return this._showHints;\r\n }\r\n\r\n get isQuiz(): boolean {\r\n return this._isQuiz;\r\n }\r\n\r\n get userEventLog(): string[] {\r\n return [...this._userEventLog];\r\n }\r\n\r\n get currentStepIndex(): number {\r\n return this._currentStepIndex;\r\n }\r\n\r\n get isComplete(): boolean {\r\n const expected = this.evaluatedEventIds;\r\n if (expected.length === 0) return false;\r\n\r\n if (this._orderMatters) {\r\n return this._currentStepIndex >= expected.length;\r\n } else {\r\n const requiredEvents = new Set(expected);\r\n const emittedEvents = new Set(this.evaluatedUserEventLog);\r\n return Array.from(requiredEvents).every((event) =>\r\n emittedEvents.has(event),\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Whether a step takes part in evaluation (#53). In training every authored\r\n * step counts. In quiz mode only \"assessed\" steps do: instructional steps are\r\n * quiz-neutral, so they are filtered out of BOTH the authored list and the\r\n * student's log before any scoring, progress, completion or hint decision.\r\n * Categories come from the injected lookup at call time, never from state.\r\n */\r\n private isEvaluated(eventId: string): boolean {\r\n return !this._isQuiz || this._getEventCategory(eventId) === \"assessed\";\r\n }\r\n\r\n /** The authored steps that are evaluated (all of them outside quiz mode). */\r\n private get evaluatedEventIds(): string[] {\r\n return this._eventIds.filter((eventId) => this.isEvaluated(eventId));\r\n }\r\n\r\n /** The student's log restricted to evaluated steps. */\r\n private get evaluatedUserEventLog(): string[] {\r\n return this._userEventLog.filter((eventId) => this.isEvaluated(eventId));\r\n }\r\n\r\n /**\r\n * The validation message for a quiz whose authored steps are all\r\n * instructional (#53), or null when it is not that case. Such a quiz has\r\n * events but nothing to score — scoring, progress and completion all run on\r\n * the empty assessed subsequence — so it must be flagged rather than silently\r\n * treated as valid.\r\n */\r\n private get quizNeedsAssessedStepMessage(): string | null {\r\n return this._isQuiz && this.evaluatedEventIds.length === 0\r\n ? \"A quiz needs at least one assessed step\"\r\n : null;\r\n }\r\n\r\n get validationMessage(): string | null {\r\n return this._validationMessage;\r\n }\r\n\r\n get score(): {\r\n percentage: number;\r\n comparison: {eventId: string; expected: boolean; actual: boolean; correct: boolean}[];\r\n } | null {\r\n return this._score;\r\n }\r\n\r\n get isSubmitted(): boolean {\r\n return this._isSubmitted;\r\n }\r\n\r\n addEventId(eventId: string): void {\r\n if (this._eventIds.includes(eventId)) {\r\n this._validationMessage = `Event '${eventId}' is already in the procedure`;\r\n this.updateState();\r\n return;\r\n }\r\n\r\n this._eventIds.push(eventId);\r\n this._validationMessage = null;\r\n this.updateState();\r\n }\r\n\r\n removeEventId(eventId: string): void {\r\n const index = this._eventIds.indexOf(eventId);\r\n if (index === -1) {\r\n this._validationMessage = `Event '${eventId}' is not in the procedure`;\r\n this.updateState();\r\n return;\r\n }\r\n\r\n this._eventIds.splice(index, 1);\r\n this._validationMessage = null;\r\n this.updateState();\r\n }\r\n\r\n clearEventIds(): void {\r\n this._eventIds = [];\r\n this._validationMessage = null;\r\n this.updateState();\r\n }\r\n\r\n moveEventUp(index: number): void {\r\n if (index <= 0 || index >= this._eventIds.length) {\r\n this._validationMessage = \"Cannot move event up - invalid position\";\r\n this.updateState();\r\n return;\r\n }\r\n\r\n const temp = this._eventIds[index];\r\n this._eventIds[index] = this._eventIds[index - 1];\r\n this._eventIds[index - 1] = temp;\r\n\r\n this._validationMessage = null;\r\n this.updateState();\r\n }\r\n\r\n moveEventDown(index: number): void {\r\n if (index < 0 || index >= this._eventIds.length - 1) {\r\n this._validationMessage = \"Cannot move event down - invalid position\";\r\n this.updateState();\r\n return;\r\n }\r\n\r\n const temp = this._eventIds[index];\r\n this._eventIds[index] = this._eventIds[index + 1];\r\n this._eventIds[index + 1] = temp;\r\n\r\n this._validationMessage = null;\r\n this.updateState();\r\n }\r\n\r\n recordUserEvent(eventId: string): void {\r\n if (!this._eventIds.includes(eventId)) {\r\n return;\r\n }\r\n\r\n if (!this.isEvaluated(eventId)) {\r\n // Quiz mode, instructional step: quiz-neutral. Record it once as evidence\r\n // the student reached this guidance step, but a re-emission (e.g.\r\n // revisiting a viewpoint) is not re-logged — mirroring the benign-revisit\r\n // rule for assessed steps and keeping the log bounded no matter how often\r\n // the student oscillates. It never advances the attempt nor flags a wrong\r\n // step; however they got here counts the same.\r\n if (!this._userEventLog.includes(eventId)) {\r\n this._userEventLog.push(eventId);\r\n this.updateState();\r\n }\r\n return;\r\n }\r\n\r\n if (this._orderMatters && this.isBenignRevisit(eventId)) {\r\n // Re-emission of an already-completed step (a toggle, a navigation\r\n // arrival, an accidental double-trigger). It carries no information about\r\n // the attempt, so it neither enters the log nor flashes a hint.\r\n return;\r\n }\r\n\r\n this._userEventLog.push(eventId);\r\n\r\n if (this._orderMatters) {\r\n const expected = this.evaluatedEventIds;\r\n if (this._currentStepIndex < expected.length) {\r\n const expectedEvent = expected[this._currentStepIndex];\r\n if (eventId === expectedEvent) {\r\n this._currentStepIndex++;\r\n this._validationMessage = null;\r\n } else {\r\n this._validationMessage = `Expected '${expectedEvent}', but got '${eventId}'`;\r\n }\r\n }\r\n }\r\n\r\n this.updateState();\r\n }\r\n\r\n /**\r\n * An event is a benign revisit when it is an evaluated step that has already\r\n * been completed. Well-defined because addEventId guarantees eventIds are\r\n * unique, so indexOf identifies the step. An early emission of a LATER step\r\n * is not a revisit and is still logged and flagged. `currentStepIndex`\r\n * indexes the evaluated list, so the lookup is against that list too.\r\n */\r\n private isBenignRevisit(eventId: string): boolean {\r\n const stepIndex = this.evaluatedEventIds.indexOf(eventId);\r\n return stepIndex !== -1 && stepIndex < this._currentStepIndex;\r\n }\r\n\r\n validateProgress(): string | null {\r\n if (this._eventIds.length === 0) {\r\n return \"At least one event must be added to the procedure\";\r\n }\r\n\r\n const quizMessage = this.quizNeedsAssessedStepMessage;\r\n if (quizMessage) {\r\n return quizMessage;\r\n }\r\n\r\n if (this.isComplete) {\r\n return null;\r\n }\r\n\r\n if (this._orderMatters && this._validationMessage) {\r\n return this._validationMessage;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n getNextExpectedEvent(): string | null {\r\n const expected = this.evaluatedEventIds;\r\n if (!this._showHints || expected.length === 0) {\r\n return null;\r\n }\r\n\r\n if (this._orderMatters) {\r\n if (this._currentStepIndex < expected.length) {\r\n return expected[this._currentStepIndex];\r\n }\r\n } else {\r\n const emittedEvents = new Set(this.evaluatedUserEventLog);\r\n return expected.find((eventId) => !emittedEvents.has(eventId)) || null;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n reset(): void {\r\n this._userEventLog = [];\r\n this._currentStepIndex = 0;\r\n this._validationMessage = null;\r\n this._score = null;\r\n this._isSubmitted = false;\r\n this.updateState();\r\n }\r\n\r\n setOrderMatters(orderMatters: boolean): void {\r\n this._orderMatters = orderMatters;\r\n this.updateState();\r\n }\r\n\r\n setShowHints(showHints: boolean): void {\r\n this._showHints = showHints;\r\n this.updateState();\r\n }\r\n\r\n setIsQuiz(isQuiz: boolean): void {\r\n this._isQuiz = isQuiz;\r\n this.updateState();\r\n }\r\n\r\n get isRecording(): boolean {\r\n return this._isRecording;\r\n }\r\n\r\n setIsRecording(value: boolean): void {\r\n this._isRecording = value;\r\n this.updateState();\r\n }\r\n\r\n setEventCategoryLookup(lookup: EventCategoryLookup): void {\r\n // Wiring, not serialized state: it is not part of the state hash. Notify\r\n // directly so a PM built before the factory wired the lookup rebuilds.\r\n this._getEventCategory = lookup;\r\n this.notifyOnChange();\r\n }\r\n\r\n getEventCategory(eventId: string): EventCategory {\r\n return this._getEventCategory(eventId);\r\n }\r\n\r\n getProgressPercentage(): number {\r\n const expected = this.evaluatedEventIds;\r\n if (expected.length === 0) return 0;\r\n\r\n if (this._orderMatters) {\r\n return Math.round((this._currentStepIndex / expected.length) * 100);\r\n } else {\r\n const requiredEvents = new Set(expected);\r\n const emittedEvents = new Set(this.evaluatedUserEventLog);\r\n const completedCount = Array.from(requiredEvents).filter((event) =>\r\n emittedEvents.has(event),\r\n ).length;\r\n return Math.round((completedCount / expected.length) * 100);\r\n }\r\n }\r\n\r\n calculateScore(): {\r\n percentage: number;\r\n comparison: {eventId: string; expected: boolean; actual: boolean; correct: boolean}[];\r\n } {\r\n // In quiz mode only assessed steps are scored (#53): instructional steps\r\n // are dropped from BOTH the expected list and the log, so a quiz made only\r\n // of instructional steps scores like an empty procedure.\r\n const expectedIds = this.evaluatedEventIds;\r\n if (expectedIds.length === 0) {\r\n return { percentage: 0, comparison: [] };\r\n }\r\n\r\n const comparison: {eventId: string; expected: boolean; actual: boolean; correct: boolean}[] = [];\r\n let correctCount = 0;\r\n\r\n if (this._orderMatters) {\r\n // The score answers \"did the student perform the required steps in the\r\n // required order?\" — so it is the longest run of expected steps that\r\n // appear in order in the log, not a positional index-by-index compare\r\n // (which collapsed to near zero after a single extra, skipped, or\r\n // repeated step). Extra authored events are not penalized here.\r\n // Both arrays are already the assessed subsequence in quiz mode, so an\r\n // instructional emission can never shift the alignment.\r\n const matched = alignBySubsequence(expectedIds, this.evaluatedUserEventLog);\r\n for (let i = 0; i < expectedIds.length; i++) {\r\n const eventId = expectedIds[i];\r\n const expected = true;\r\n const actual = matched[i];\r\n const correct = actual;\r\n\r\n comparison.push({ eventId, expected, actual, correct });\r\n if (correct) correctCount++;\r\n }\r\n } else {\r\n const emittedEvents = new Set(this.evaluatedUserEventLog);\r\n for (const eventId of expectedIds) {\r\n const expected = true;\r\n const actual = emittedEvents.has(eventId);\r\n const correct = actual;\r\n\r\n comparison.push({ eventId, expected, actual, correct });\r\n if (correct) correctCount++;\r\n }\r\n }\r\n\r\n const percentage = Math.round((correctCount / expectedIds.length) * 100);\r\n return { percentage, comparison };\r\n }\r\n\r\n submit(): void {\r\n if (!this._isQuiz) {\r\n this._validationMessage = \"Cannot submit: not in quiz mode\";\r\n this.updateState();\r\n return;\r\n }\r\n\r\n this._score = this.calculateScore();\r\n this._isSubmitted = true;\r\n this._validationMessage = null;\r\n this.updateState();\r\n }\r\n\r\n getAuthoringValidationMessage(): string | null {\r\n if (this._eventIds.length === 0) {\r\n return \"At least one event must be added to the procedure\";\r\n }\r\n return this.quizNeedsAssessedStepMessage ?? this._validationMessage;\r\n }\r\n\r\n private updateState(): void {\r\n const stateHash = JSON.stringify({\r\n eventIds: this._eventIds,\r\n orderMatters: this._orderMatters,\r\n showHints: this._showHints,\r\n isQuiz: this._isQuiz,\r\n userEventLog: this._userEventLog,\r\n currentStepIndex: this._currentStepIndex,\r\n validationMessage: this._validationMessage,\r\n score: this._score,\r\n isSubmitted: this._isSubmitted,\r\n isRecording: this._isRecording,\r\n });\r\n\r\n this.memoizedState.val = stateHash;\r\n }\r\n\r\n constructor(appObject: AppObject) {\r\n super(appObject, ProcedureEntity.type);\r\n this.appObjects.registerSingleton(this);\r\n this.updateState();\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"ProcedureEntity.js","sourceRoot":"","sources":["../../../../src/Procedure/Entities/ProcedureEntity.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AppObject,\n AppObjectEntity,\n AppObjectRepo,\n getSingletonComponent,\n MemoizedString,\n} from \"@vived/core\";\nimport { Challenge } from \"../../Challenge\";\nimport { EventCategory } from \"../../EventSystem/types\";\nimport { EventCategoryLookup } from \"../types\";\n\nexport abstract class ProcedureEntity\n extends AppObjectEntity\n implements Challenge\n{\n static readonly type = \"ProcedureEntity\";\n\n readonly challengeID = \"PROCEDURE\";\n name = \"Procedure\";\n abstract get helpHeading(): string;\n abstract get consumerHelpText(): string;\n authorHelpText =\n \"Create step-by-step procedures by selecting events that users must emit.\";\n\n abstract get eventIds(): string[];\n abstract get orderMatters(): boolean;\n abstract get showHints(): boolean;\n abstract get isQuiz(): boolean;\n abstract get userEventLog(): string[];\n abstract get currentStepIndex(): number;\n abstract get isComplete(): boolean;\n abstract get validationMessage(): string | null;\n abstract get score(): {\n percentage: number;\n comparison: {\n eventId: string;\n expected: boolean;\n actual: boolean;\n correct: boolean;\n }[];\n } | null;\n abstract get isSubmitted(): boolean;\n\n abstract addEventId(eventId: string): void;\n abstract removeEventId(eventId: string): void;\n abstract clearEventIds(): void;\n abstract recordUserEvent(eventId: string): void;\n abstract validateProgress(): string | null;\n abstract getNextExpectedEvent(): string | null;\n abstract reset(): void;\n abstract moveEventUp(index: number): void;\n abstract moveEventDown(index: number): void;\n abstract getAuthoringValidationMessage(): string | null;\n\n abstract setOrderMatters(orderMatters: boolean): void;\n abstract setShowHints(showHints: boolean): void;\n abstract setIsQuiz(isQuiz: boolean): void;\n\n abstract get isRecording(): boolean;\n abstract setIsRecording(value: boolean): void;\n\n /**\n * Inject the Registry lookup used to classify steps (#53). Wired by the\n * FeatureFactory; evaluated at call time so late registrations are seen.\n * With no lookup injected every step is \"assessed\".\n */\n abstract setEventCategoryLookup(lookup: EventCategoryLookup): void;\n /** The category of an authored (or any) event id, via the injected lookup. */\n abstract getEventCategory(eventId: string): EventCategory;\n\n abstract getProgressPercentage(): number;\n abstract calculateScore(): {\n percentage: number;\n comparison: {\n eventId: string;\n expected: boolean;\n actual: boolean;\n correct: boolean;\n }[];\n };\n abstract submit(): void;\n\n static get = (appObjects: AppObjectRepo): ProcedureEntity | undefined =>\n getSingletonComponent(ProcedureEntity.type, appObjects);\n}\n\nexport function makeProcedureEntity(appObject: AppObject): ProcedureEntity {\n return new ProcedureEntityImp(appObject);\n}\n\n/**\n * Aligns `actual` against `expected` by longest common subsequence (LCS) and\n * reports, for each index of `expected`, whether that step takes part in the\n * alignment. `matched.filter(Boolean).length` is the LCS length.\n *\n * Pure function over two plain arrays: callers decide what goes in. That is the\n * seam for event categories (#53) — pre-filter both arrays to the assessed\n * subsequence and nothing in here needs to change.\n *\n * Deterministic tie-break: when several alignments share the maximum length\n * (e.g. two swapped steps), the one that matches the EARLIEST expected steps\n * wins, so the same step is reported incorrect on every run.\n *\n * O(n·m) dynamic programming; procedures are ~20 steps at most.\n */\nfunction alignBySubsequence(expected: string[], actual: string[]): boolean[] {\n const n = expected.length;\n const m = actual.length;\n\n // lcs[i][j] = LCS length of expected[i..] against actual[j..]\n const lcs: number[][] = Array.from({ length: n + 1 }, () =>\n new Array<number>(m + 1).fill(0),\n );\n for (let i = n - 1; i >= 0; i--) {\n for (let j = m - 1; j >= 0; j--) {\n lcs[i][j] =\n expected[i] === actual[j]\n ? lcs[i + 1][j + 1] + 1\n : Math.max(lcs[i + 1][j], lcs[i][j + 1]);\n }\n }\n\n // Walk forward from the start. Matching an equal pair is always optimal.\n // On a mismatch, prefer skipping the actual entry whenever that costs\n // nothing, which keeps the current (earliest) expected step in play.\n const matched = new Array<boolean>(n).fill(false);\n let e = 0; // index into expected\n let a = 0; // index into actual\n while (e < n && a < m) {\n if (expected[e] === actual[a]) {\n matched[e] = true;\n e++;\n a++;\n } else if (lcs[e][a + 1] === lcs[e][a]) {\n a++;\n } else {\n e++;\n }\n }\n return matched;\n}\n\nclass ProcedureEntityImp extends ProcedureEntity {\n private _eventIds: string[] = [];\n private _orderMatters = true;\n private _showHints = true;\n private _isQuiz = false;\n private _isRecording = false;\n private _userEventLog: string[] = [];\n private _currentStepIndex = 0;\n private _validationMessage: string | null = null;\n private _score: {\n percentage: number;\n comparison: {\n eventId: string;\n expected: boolean;\n actual: boolean;\n correct: boolean;\n }[];\n } | null = null;\n private _isSubmitted = false;\n private _getEventCategory: EventCategoryLookup = () => \"assessed\";\n\n get helpHeading(): string {\n if (this._isQuiz) return \"Procedure Challenge\";\n else return \"Procedure Training\";\n }\n\n get consumerHelpText(): string {\n if (this._isQuiz)\n return \"Complete the procedure challenge on your own and get scored after submitting.\";\n else return \"Follow the steps in order to complete the training procedure.\";\n }\n\n private memoizedState = new MemoizedString(\"\", this.notifyOnChange);\n\n get eventIds(): string[] {\n return [...this._eventIds];\n }\n\n get orderMatters(): boolean {\n return this._orderMatters;\n }\n\n get showHints(): boolean {\n return this._showHints;\n }\n\n get isQuiz(): boolean {\n return this._isQuiz;\n }\n\n get userEventLog(): string[] {\n return [...this._userEventLog];\n }\n\n get currentStepIndex(): number {\n return this._currentStepIndex;\n }\n\n get isComplete(): boolean {\n const expected = this.evaluatedEventIds;\n if (expected.length === 0) return false;\n\n if (this._orderMatters) {\n return this._currentStepIndex >= expected.length;\n } else {\n const requiredEvents = new Set(expected);\n const emittedEvents = new Set(this.evaluatedUserEventLog);\n return Array.from(requiredEvents).every((event) =>\n emittedEvents.has(event),\n );\n }\n }\n\n /**\n * Whether a step takes part in evaluation (#53). In training every authored\n * step counts. In quiz mode only \"assessed\" steps do: instructional steps are\n * quiz-neutral, so they are filtered out of BOTH the authored list and the\n * student's log before any scoring, progress, completion or hint decision.\n * Categories come from the injected lookup at call time, never from state.\n */\n private isEvaluated(eventId: string): boolean {\n return !this._isQuiz || this._getEventCategory(eventId) === \"assessed\";\n }\n\n /** The authored steps that are evaluated (all of them outside quiz mode). */\n private get evaluatedEventIds(): string[] {\n return this._eventIds.filter((eventId) => this.isEvaluated(eventId));\n }\n\n /** The student's log restricted to evaluated steps. */\n private get evaluatedUserEventLog(): string[] {\n return this._userEventLog.filter((eventId) => this.isEvaluated(eventId));\n }\n\n /**\n * The validation message for a quiz whose authored steps are all\n * instructional (#53), or null when it is not that case. Such a quiz has\n * events but nothing to score — scoring, progress and completion all run on\n * the empty assessed subsequence — so it must be flagged rather than silently\n * treated as valid.\n */\n private get quizNeedsAssessedStepMessage(): string | null {\n return this._isQuiz && this.evaluatedEventIds.length === 0\n ? \"A quiz needs at least one assessed step\"\n : null;\n }\n\n get validationMessage(): string | null {\n return this._validationMessage;\n }\n\n get score(): {\n percentage: number;\n comparison: {\n eventId: string;\n expected: boolean;\n actual: boolean;\n correct: boolean;\n }[];\n } | null {\n return this._score;\n }\n\n get isSubmitted(): boolean {\n return this._isSubmitted;\n }\n\n addEventId(eventId: string): void {\n if (this._eventIds.includes(eventId)) {\n this._validationMessage = `Event '${eventId}' is already in the procedure`;\n this.updateState();\n return;\n }\n\n this._eventIds.push(eventId);\n this._validationMessage = null;\n this.updateState();\n }\n\n removeEventId(eventId: string): void {\n const index = this._eventIds.indexOf(eventId);\n if (index === -1) {\n this._validationMessage = `Event '${eventId}' is not in the procedure`;\n this.updateState();\n return;\n }\n\n this._eventIds.splice(index, 1);\n this._validationMessage = null;\n this.updateState();\n }\n\n clearEventIds(): void {\n this._eventIds = [];\n this._validationMessage = null;\n this.updateState();\n }\n\n moveEventUp(index: number): void {\n if (index <= 0 || index >= this._eventIds.length) {\n this._validationMessage = \"Cannot move event up - invalid position\";\n this.updateState();\n return;\n }\n\n const temp = this._eventIds[index];\n this._eventIds[index] = this._eventIds[index - 1];\n this._eventIds[index - 1] = temp;\n\n this._validationMessage = null;\n this.updateState();\n }\n\n moveEventDown(index: number): void {\n if (index < 0 || index >= this._eventIds.length - 1) {\n this._validationMessage = \"Cannot move event down - invalid position\";\n this.updateState();\n return;\n }\n\n const temp = this._eventIds[index];\n this._eventIds[index] = this._eventIds[index + 1];\n this._eventIds[index + 1] = temp;\n\n this._validationMessage = null;\n this.updateState();\n }\n\n recordUserEvent(eventId: string): void {\n if (!this._eventIds.includes(eventId)) {\n return;\n }\n\n if (!this.isEvaluated(eventId)) {\n // Quiz mode, instructional step: quiz-neutral. Record it once as evidence\n // the student reached this guidance step, but a re-emission (e.g.\n // revisiting a viewpoint) is not re-logged — mirroring the benign-revisit\n // rule for assessed steps and keeping the log bounded no matter how often\n // the student oscillates. It never advances the attempt nor flags a wrong\n // step; however they got here counts the same.\n if (!this._userEventLog.includes(eventId)) {\n this._userEventLog.push(eventId);\n this.updateState();\n }\n return;\n }\n\n if (this._orderMatters && this.isBenignRevisit(eventId)) {\n // Re-emission of an already-completed step (a toggle, a navigation\n // arrival, an accidental double-trigger). It carries no information about\n // the attempt, so it neither enters the log nor flashes a hint.\n return;\n }\n\n this._userEventLog.push(eventId);\n\n if (this._orderMatters) {\n const expected = this.evaluatedEventIds;\n if (this._currentStepIndex < expected.length) {\n const expectedEvent = expected[this._currentStepIndex];\n if (eventId === expectedEvent) {\n this._currentStepIndex++;\n this._validationMessage = null;\n } else {\n this._validationMessage = `Expected '${expectedEvent}', but got '${eventId}'`;\n }\n }\n }\n\n this.updateState();\n }\n\n /**\n * An event is a benign revisit when it is an evaluated step that has already\n * been completed. Well-defined because addEventId guarantees eventIds are\n * unique, so indexOf identifies the step. An early emission of a LATER step\n * is not a revisit and is still logged and flagged. `currentStepIndex`\n * indexes the evaluated list, so the lookup is against that list too.\n */\n private isBenignRevisit(eventId: string): boolean {\n const stepIndex = this.evaluatedEventIds.indexOf(eventId);\n return stepIndex !== -1 && stepIndex < this._currentStepIndex;\n }\n\n validateProgress(): string | null {\n if (this._eventIds.length === 0) {\n return \"At least one event must be added to the procedure\";\n }\n\n const quizMessage = this.quizNeedsAssessedStepMessage;\n if (quizMessage) {\n return quizMessage;\n }\n\n if (this.isComplete) {\n return null;\n }\n\n if (this._orderMatters && this._validationMessage) {\n return this._validationMessage;\n }\n\n return null;\n }\n\n getNextExpectedEvent(): string | null {\n const expected = this.evaluatedEventIds;\n if (!this._showHints || expected.length === 0) {\n return null;\n }\n\n if (this._orderMatters) {\n if (this._currentStepIndex < expected.length) {\n return expected[this._currentStepIndex];\n }\n } else {\n const emittedEvents = new Set(this.evaluatedUserEventLog);\n return expected.find((eventId) => !emittedEvents.has(eventId)) || null;\n }\n\n return null;\n }\n\n reset(): void {\n this._userEventLog = [];\n this._currentStepIndex = 0;\n this._validationMessage = null;\n this._score = null;\n this._isSubmitted = false;\n this.updateState();\n }\n\n setOrderMatters(orderMatters: boolean): void {\n this._orderMatters = orderMatters;\n this.updateState();\n }\n\n setShowHints(showHints: boolean): void {\n this._showHints = showHints;\n this.updateState();\n }\n\n setIsQuiz(isQuiz: boolean): void {\n this._isQuiz = isQuiz;\n this.updateState();\n }\n\n get isRecording(): boolean {\n return this._isRecording;\n }\n\n setIsRecording(value: boolean): void {\n this._isRecording = value;\n this.updateState();\n }\n\n setEventCategoryLookup(lookup: EventCategoryLookup): void {\n // Wiring, not serialized state: it is not part of the state hash. Notify\n // directly so a PM built before the factory wired the lookup rebuilds.\n this._getEventCategory = lookup;\n this.notifyOnChange();\n }\n\n getEventCategory(eventId: string): EventCategory {\n return this._getEventCategory(eventId);\n }\n\n getProgressPercentage(): number {\n const expected = this.evaluatedEventIds;\n if (expected.length === 0) return 0;\n\n if (this._orderMatters) {\n return Math.round((this._currentStepIndex / expected.length) * 100);\n } else {\n const requiredEvents = new Set(expected);\n const emittedEvents = new Set(this.evaluatedUserEventLog);\n const completedCount = Array.from(requiredEvents).filter((event) =>\n emittedEvents.has(event),\n ).length;\n return Math.round((completedCount / expected.length) * 100);\n }\n }\n\n calculateScore(): {\n percentage: number;\n comparison: {\n eventId: string;\n expected: boolean;\n actual: boolean;\n correct: boolean;\n }[];\n } {\n // In quiz mode only assessed steps are scored (#53): instructional steps\n // are dropped from BOTH the expected list and the log, so a quiz made only\n // of instructional steps scores like an empty procedure.\n const expectedIds = this.evaluatedEventIds;\n if (expectedIds.length === 0) {\n return { percentage: 0, comparison: [] };\n }\n\n const comparison: {\n eventId: string;\n expected: boolean;\n actual: boolean;\n correct: boolean;\n }[] = [];\n let correctCount = 0;\n\n if (this._orderMatters) {\n // The score answers \"did the student perform the required steps in the\n // required order?\" — so it is the longest run of expected steps that\n // appear in order in the log, not a positional index-by-index compare\n // (which collapsed to near zero after a single extra, skipped, or\n // repeated step). Extra authored events are not penalized here.\n // Both arrays are already the assessed subsequence in quiz mode, so an\n // instructional emission can never shift the alignment.\n const matched = alignBySubsequence(\n expectedIds,\n this.evaluatedUserEventLog,\n );\n for (let i = 0; i < expectedIds.length; i++) {\n const eventId = expectedIds[i];\n const expected = true;\n const actual = matched[i];\n const correct = actual;\n\n comparison.push({ eventId, expected, actual, correct });\n if (correct) correctCount++;\n }\n } else {\n const emittedEvents = new Set(this.evaluatedUserEventLog);\n for (const eventId of expectedIds) {\n const expected = true;\n const actual = emittedEvents.has(eventId);\n const correct = actual;\n\n comparison.push({ eventId, expected, actual, correct });\n if (correct) correctCount++;\n }\n }\n\n const percentage = Math.round((correctCount / expectedIds.length) * 100);\n return { percentage, comparison };\n }\n\n submit(): void {\n if (!this._isQuiz) {\n this._validationMessage = \"Cannot submit: not in quiz mode\";\n this.updateState();\n return;\n }\n\n this._score = this.calculateScore();\n this._isSubmitted = true;\n this._validationMessage = null;\n this.updateState();\n }\n\n getAuthoringValidationMessage(): string | null {\n if (this._eventIds.length === 0) {\n return \"At least one event must be added to the procedure\";\n }\n return this.quizNeedsAssessedStepMessage ?? this._validationMessage;\n }\n\n private updateState(): void {\n const stateHash = JSON.stringify({\n eventIds: this._eventIds,\n orderMatters: this._orderMatters,\n showHints: this._showHints,\n isQuiz: this._isQuiz,\n userEventLog: this._userEventLog,\n currentStepIndex: this._currentStepIndex,\n validationMessage: this._validationMessage,\n score: this._score,\n isSubmitted: this._isSubmitted,\n isRecording: this._isRecording,\n });\n\n this.memoizedState.val = stateHash;\n }\n\n constructor(appObject: AppObject) {\n super(appObject, ProcedureEntity.type);\n this.appObjects.registerSingleton(this);\n this.updateState();\n }\n}\n"]}
@@ -247,18 +247,7 @@ describe("ProcedureEntity", () => {
247
247
  });
248
248
  });
249
249
  describe("calculateScore (order matters, 10 steps)", () => {
250
- const steps = [
251
- "s1",
252
- "s2",
253
- "s3",
254
- "s4",
255
- "s5",
256
- "s6",
257
- "s7",
258
- "s8",
259
- "s9",
260
- "s10",
261
- ];
250
+ const steps = ["s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10"];
262
251
  const record = (...ids) => ids.forEach((id) => procedureEntity.recordUserEvent(id));
263
252
  const correctFlags = () => procedureEntity.calculateScore().comparison.map((c) => c.correct);
264
253
  beforeEach(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"ProcedureEntity.test.js","sourceRoot":"","sources":["../../../../src/Procedure/Entities/ProcedureEntity.test.ts"],"names":[],"mappings":";;AAAA,sCAA+D;AAC/D,uDAAyE;AAEzE,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAChC,IAAI,UAAyB,CAAC;IAC9B,IAAI,eAAgC,CAAC;IAErC,UAAU,CAAC,GAAG,EAAE;QACf,UAAU,GAAG,IAAA,wBAAiB,GAAE,CAAC;QACjC,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;QAC1D,eAAe,GAAG,IAAA,qCAAmB,EAAC,SAAS,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACtD,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/D,MAAM,CAAC,OAAO,eAAe,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7D,MAAM,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC/D,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAChE,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAC5C,+DAA+D,CAC/D,CAAC;QACF,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAC5C,+EAA+E,CAC/E,CAAC;QACF,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAC5C,+DAA+D,CAC/D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC7C,MAAM,SAAS,GAAG,iCAAe,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAClD,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACtC,eAAe,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAC3C,eAAe,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACpC,eAAe,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;QACzC,eAAe,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;QACzC,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC3C,eAAe,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAC3C,eAAe,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAC3C,eAAe,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;QAC9C,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC/C,eAAe,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;QAC9C,MAAM,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC/B,eAAe,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAC3C,eAAe,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAC3C,eAAe,CAAC,aAAa,EAAE,CAAC;QAChC,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC3C,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACrD,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjD,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAChD,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC,SAAS,CAClD,uCAAuC,CACvC,CAAC;QACF,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAChD,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACvC,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QAC1C,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;QACjD,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QACnD,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACrD,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC7C,eAAe,CAAC,aAAa,EAAE,CAAC;QAChC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACrD,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxD,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzD,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzD,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACvD,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxD,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzD,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QACjF,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACtC,eAAe,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,CAAC,eAAe,CAAC,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/D,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACpF,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACvC,eAAe,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,CAAC,eAAe,CAAC,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/D,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/D,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC/C,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,CAAC,eAAe,CAAC,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,eAAe,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QACnC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,eAAe,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC9D,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,eAAe,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACvC,eAAe,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACpC,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAChC,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpD,eAAe,CAAC,KAAK,EAAE,CAAC;QACxB,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QACjE,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,0CAA0C,EAAE,GAAG,EAAE;QACzD,UAAU,CAAC,GAAG,EAAE;YACf,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACjC,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACjC,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACjC,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;YAClE,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;YAC3D,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YACjE,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE,CAAC;QACtD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YACjE,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;YAC3D,MAAM,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAC7C,6BAA6B,CAC7B,CAAC;YACF,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,0CAA0C,EAAE,GAAG,EAAE;QACzD,MAAM,KAAK,GAAG;YACb,IAAI;YACJ,IAAI;YACJ,IAAI;YACJ,IAAI;YACJ,IAAI;YACJ,IAAI;YACJ,IAAI;YACJ,IAAI;YACJ,IAAI;YACJ,KAAK;SACL,CAAC;QAEF,MAAM,MAAM,GAAG,CAAC,GAAG,GAAa,EAAE,EAAE,CACnC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC;QAE1D,MAAM,YAAY,GAAG,GAAG,EAAE,CACzB,eAAe,CAAC,cAAc,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAEnE,UAAU,CAAC,GAAG,EAAE;YACf,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YACpD,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC5D,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC;YACjB,MAAM,KAAK,GAAG,eAAe,CAAC,cAAc,EAAE,CAAC;YAC/C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC9D,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;YACnE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAC1E,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9D,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;YACvE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAC9D,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC7D,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC;gBAC9B,IAAI;gBACJ,IAAI;gBACJ,IAAI;gBACJ,IAAI;gBACJ,KAAK;gBACL,IAAI;gBACJ,IAAI;gBACJ,IAAI;gBACJ,IAAI;gBACJ,IAAI;aACJ,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uFAAuF,EAAE,GAAG,EAAE;YAChG,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YACpE,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;gBAClC,MAAM,KAAK,GAAG,eAAe,CAAC,cAAc,EAAE,CAAC;gBAC/C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAClC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAChD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClE,CAAC;QACF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;YACzE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAC1E,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpD,MAAM,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE,CAAC;YACrD,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9D,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YAC1C,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YAChC,MAAM,KAAK,GAAG,eAAe,CAAC,cAAc,EAAE,CAAC;YAC/C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC3D,MAAM,KAAK,GAAG,eAAe,CAAC,cAAc,EAAE,CAAC;YAC/C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1D,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC9B,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC9B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;YAC5E,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAC9D,MAAM,OAAO,GAAG,eAAe,CAAC,cAAc,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC/D,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;gBACvB,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,KAAK;aACd,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;QAC1C,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;YAC3E,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC;gBAChD,UAAU,EAAE,CAAC;gBACb,UAAU,EAAE,EAAE;aACd,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;YAC7D,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAChC,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAChC,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAChC,eAAe,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YACvC,eAAe,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YACrC,eAAe,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YACrC,MAAM,KAAK,GAAG,eAAe,CAAC,cAAc,EAAE,CAAC;YAC/C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;gBACtD,IAAI;gBACJ,KAAK;gBACL,IAAI;aACJ,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;YACnE,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,CACpE,UAAU,CACV,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;YAC9E,eAAe,CAAC,sBAAsB,CAAC,CAAC,OAAO,EAAE,EAAE,CAClD,OAAO,KAAK,sBAAsB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,UAAU,CACjE,CAAC;YAEF,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,CACpE,eAAe,CACf,CAAC;YACF,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;YAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;YAC3B,eAAe,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAE5C,eAAe,CAAC,sBAAsB,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC;YAEzD,MAAM,CAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,0CAA0C,EAAE,GAAG,EAAE;QACzD,MAAM,GAAG,GAAG,sBAAsB,CAAC;QAEnC,UAAU,CAAC,GAAG,EAAE;YACf,eAAe,CAAC,sBAAsB,CAAC,CAAC,OAAO,EAAE,EAAE,CAClD,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,UAAU,CAC9C,CAAC;YACF,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAChC,eAAe,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACpC,eAAe,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACpC,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC/C,eAAe,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACzC,eAAe,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YAEzC,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC;gBAChD,UAAU,EAAE,GAAG;gBACf,UAAU,EAAE;oBACX,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;oBACjE,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;iBACjE;aACD,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;YACnF,eAAe,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YAErC,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACpD,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjD,MAAM,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE,CAAC;YACrD,MAAM,CAAC,eAAe,CAAC,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;YAClF,eAAe,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACzC,eAAe,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YACrC,eAAe,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YAEzC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9C,MAAM,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1D,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;YACjF,eAAe,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACvC,eAAe,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAEvC,eAAe,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YAErC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/C,MAAM,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACxD,MAAM,CAAC,eAAe,CAAC,oBAAoB,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC1D,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC;gBAChD,UAAU,EAAE,CAAC;gBACb,UAAU,EAAE,EAAE;aACd,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;YACvD,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAEjC,eAAe,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YACrC,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjD,MAAM,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEzD,eAAe,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACzC,eAAe,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACzC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9C,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sFAAsF,EAAE,GAAG,EAAE;YAC/F,eAAe,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YACrC,eAAe,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACzC,eAAe,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YACrC,eAAe,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YAErC,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;YAC7D,oDAAoD;YACpD,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;YACrF,eAAe,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACvC,eAAe,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAEvC,MAAM,CAAC,eAAe,CAAC,6BAA6B,EAAE,CAAC,CAAC,IAAI,CAC3D,yCAAyC,CACzC,CAAC;YACF,MAAM,CAAC,eAAe,CAAC,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAC9C,yCAAyC,CACzC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2FAA2F,EAAE,GAAG,EAAE;YACpG,4DAA4D;YAC5D,MAAM,CAAC,eAAe,CAAC,6BAA6B,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;YAEnE,gEAAgE;YAChE,eAAe,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACvC,eAAe,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACvC,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,CAAC,eAAe,CAAC,6BAA6B,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACpE,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import { AppObjectRepo, makeAppObjectRepo } from \"@vived/core\";\r\nimport { ProcedureEntity, makeProcedureEntity } from \"./ProcedureEntity\";\r\n\r\ndescribe(\"ProcedureEntity\", () => {\r\n\tlet appObjects: AppObjectRepo;\r\n\tlet procedureEntity: ProcedureEntity;\r\n\r\n\tbeforeEach(() => {\r\n\t\tappObjects = makeAppObjectRepo();\r\n\t\tconst appObject = appObjects.getOrCreate(\"TestProcedure\");\r\n\t\tprocedureEntity = makeProcedureEntity(appObject);\r\n\t});\r\n\r\n\tit(\"implements Challenge interface correctly\", () => {\r\n\t\texpect(procedureEntity.challengeID).toBe(\"PROCEDURE\");\r\n\t\texpect(procedureEntity.name).toBe(\"Procedure\");\r\n\t\texpect(typeof procedureEntity.consumerHelpText).toBe(\"string\");\r\n\t\texpect(typeof procedureEntity.authorHelpText).toBe(\"string\");\r\n\t\texpect(typeof procedureEntity.reset).toBe(\"function\");\r\n\t});\r\n\r\n\tit(\"has dynamic helpHeading based on quiz mode\", () => {\r\n\t\texpect(procedureEntity.helpHeading).toBe(\"Procedure Training\");\r\n\t\tprocedureEntity.setIsQuiz(true);\r\n\t\texpect(procedureEntity.helpHeading).toBe(\"Procedure Challenge\");\r\n\t\tprocedureEntity.setIsQuiz(false);\r\n\t\texpect(procedureEntity.helpHeading).toBe(\"Procedure Training\");\r\n\t});\r\n\r\n\tit(\"has dynamic consumerHelpText based on quiz mode\", () => {\r\n\t\texpect(procedureEntity.consumerHelpText).toBe(\r\n\t\t\t\"Follow the steps in order to complete the training procedure.\",\r\n\t\t);\r\n\t\tprocedureEntity.setIsQuiz(true);\r\n\t\texpect(procedureEntity.consumerHelpText).toBe(\r\n\t\t\t\"Complete the procedure challenge on your own and get scored after submitting.\",\r\n\t\t);\r\n\t\tprocedureEntity.setIsQuiz(false);\r\n\t\texpect(procedureEntity.consumerHelpText).toBe(\r\n\t\t\t\"Follow the steps in order to complete the training procedure.\",\r\n\t\t);\r\n\t});\r\n\r\n\tit(\"has correct singleton registration\", () => {\r\n\t\tconst retrieved = ProcedureEntity.get(appObjects);\r\n\t\texpect(retrieved).toBe(procedureEntity);\r\n\t});\r\n\r\n\tit(\"starts with empty event list\", () => {\r\n\t\texpect(procedureEntity.eventIds).toEqual([]);\r\n\t});\r\n\r\n\tit(\"can add events to procedure\", () => {\r\n\t\tprocedureEntity.addEventId(\"test_event_1\");\r\n\t\tprocedureEntity.addEventId(\"test_event_2\");\r\n\t\texpect(procedureEntity.eventIds).toEqual([\"test_event_1\", \"test_event_2\"]);\r\n\t});\r\n\r\n\tit(\"prevents duplicate events\", () => {\r\n\t\tprocedureEntity.addEventId(\"test_event\");\r\n\t\tprocedureEntity.addEventId(\"test_event\");\r\n\t\texpect(procedureEntity.eventIds).toEqual([\"test_event\"]);\r\n\t\texpect(procedureEntity.validationMessage).toContain(\"already in the procedure\");\r\n\t});\r\n\r\n\tit(\"can remove events from procedure\", () => {\r\n\t\tprocedureEntity.addEventId(\"test_event_1\");\r\n\t\tprocedureEntity.addEventId(\"test_event_2\");\r\n\t\tprocedureEntity.removeEventId(\"test_event_1\");\r\n\t\texpect(procedureEntity.eventIds).toEqual([\"test_event_2\"]);\r\n\t});\r\n\r\n\tit(\"handles removing non-existent events\", () => {\r\n\t\tprocedureEntity.removeEventId(\"non_existent\");\r\n\t\texpect(procedureEntity.validationMessage).toContain(\"not in the procedure\");\r\n\t});\r\n\r\n\tit(\"can clear all events\", () => {\r\n\t\tprocedureEntity.addEventId(\"test_event_1\");\r\n\t\tprocedureEntity.addEventId(\"test_event_2\");\r\n\t\tprocedureEntity.clearEventIds();\r\n\t\texpect(procedureEntity.eventIds).toEqual([]);\r\n\t});\r\n\r\n\tit(\"starts with empty user event log\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.addEventId(\"event_2\");\r\n\t\tprocedureEntity.addEventId(\"event_3\");\r\n\t\texpect(procedureEntity.userEventLog).toEqual([]);\r\n\t\texpect(procedureEntity.currentStepIndex).toBe(0);\r\n\t\texpect(procedureEntity.isComplete).toBe(false);\r\n\t});\r\n\r\n\tit(\"records user events for ordered procedures\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.addEventId(\"event_2\");\r\n\t\tprocedureEntity.addEventId(\"event_3\");\r\n\t\tprocedureEntity.setOrderMatters(true);\r\n\t\tprocedureEntity.recordUserEvent(\"event_1\");\r\n\t\texpect(procedureEntity.userEventLog).toEqual([\"event_1\"]);\r\n\t\texpect(procedureEntity.currentStepIndex).toBe(1);\r\n\t\tprocedureEntity.recordUserEvent(\"event_2\");\r\n\t\texpect(procedureEntity.currentStepIndex).toBe(2);\r\n\t});\r\n\r\n\tit(\"validates order in ordered procedures\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.addEventId(\"event_2\");\r\n\t\tprocedureEntity.addEventId(\"event_3\");\r\n\t\tprocedureEntity.setOrderMatters(true);\r\n\t\tprocedureEntity.recordUserEvent(\"event_2\");\r\n\t\texpect(procedureEntity.validationMessage).toContain(\r\n\t\t\t\"Expected 'event_1', but got 'event_2'\",\r\n\t\t);\r\n\t\texpect(procedureEntity.currentStepIndex).toBe(0);\r\n\t});\r\n\r\n\tit(\"ignores order in unordered procedures\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.addEventId(\"event_2\");\r\n\t\tprocedureEntity.addEventId(\"event_3\");\r\n\t\tprocedureEntity.setOrderMatters(false);\r\n\t\tprocedureEntity.recordUserEvent(\"event_3\");\r\n\t\tprocedureEntity.recordUserEvent(\"event_1\");\r\n\t\texpect(procedureEntity.userEventLog).toEqual([\"event_3\", \"event_1\"]);\r\n\t});\r\n\r\n\tit(\"ignores events not in procedure\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.addEventId(\"event_2\");\r\n\t\tprocedureEntity.addEventId(\"event_3\");\r\n\t\tprocedureEntity.recordUserEvent(\"unknown_event\");\r\n\t\texpect(procedureEntity.userEventLog).toEqual([]);\r\n\t});\r\n\r\n\tit(\"detects completion in ordered procedures\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.addEventId(\"event_2\");\r\n\t\tprocedureEntity.setOrderMatters(true);\r\n\t\texpect(procedureEntity.isComplete).toBe(false);\r\n\t\tprocedureEntity.recordUserEvent(\"event_1\");\r\n\t\texpect(procedureEntity.isComplete).toBe(false);\r\n\t\tprocedureEntity.recordUserEvent(\"event_2\");\r\n\t\texpect(procedureEntity.isComplete).toBe(true);\r\n\t});\r\n\r\n\tit(\"detects completion in unordered procedures\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.addEventId(\"event_2\");\r\n\t\tprocedureEntity.setOrderMatters(false);\r\n\t\texpect(procedureEntity.isComplete).toBe(false);\r\n\t\tprocedureEntity.recordUserEvent(\"event_2\");\r\n\t\texpect(procedureEntity.isComplete).toBe(false);\r\n\t\tprocedureEntity.recordUserEvent(\"event_1\");\r\n\t\texpect(procedureEntity.isComplete).toBe(true);\r\n\t});\r\n\r\n\tit(\"returns false for empty procedures\", () => {\r\n\t\tprocedureEntity.clearEventIds();\r\n\t\texpect(procedureEntity.isComplete).toBe(false);\r\n\t});\r\n\r\n\tit(\"calculates progress for ordered procedures\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.addEventId(\"event_2\");\r\n\t\tprocedureEntity.addEventId(\"event_3\");\r\n\t\tprocedureEntity.addEventId(\"event_4\");\r\n\t\tprocedureEntity.setOrderMatters(true);\r\n\t\texpect(procedureEntity.getProgressPercentage()).toBe(0);\r\n\t\tprocedureEntity.recordUserEvent(\"event_1\");\r\n\t\texpect(procedureEntity.getProgressPercentage()).toBe(25);\r\n\t\tprocedureEntity.recordUserEvent(\"event_2\");\r\n\t\texpect(procedureEntity.getProgressPercentage()).toBe(50);\r\n\t\tprocedureEntity.recordUserEvent(\"event_3\");\r\n\t\tprocedureEntity.recordUserEvent(\"event_4\");\r\n\t\texpect(procedureEntity.getProgressPercentage()).toBe(100);\r\n\t});\r\n\r\n\tit(\"calculates progress for unordered procedures\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.addEventId(\"event_2\");\r\n\t\tprocedureEntity.addEventId(\"event_3\");\r\n\t\tprocedureEntity.addEventId(\"event_4\");\r\n\t\tprocedureEntity.setOrderMatters(false);\r\n\t\texpect(procedureEntity.getProgressPercentage()).toBe(0);\r\n\t\tprocedureEntity.recordUserEvent(\"event_3\");\r\n\t\texpect(procedureEntity.getProgressPercentage()).toBe(25);\r\n\t\tprocedureEntity.recordUserEvent(\"event_1\");\r\n\t\texpect(procedureEntity.getProgressPercentage()).toBe(50);\r\n\t});\r\n\r\n\tit(\"provides next expected event for ordered procedures with hints enabled\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.addEventId(\"event_2\");\r\n\t\tprocedureEntity.addEventId(\"event_3\");\r\n\t\tprocedureEntity.setOrderMatters(true);\r\n\t\tprocedureEntity.setShowHints(true);\r\n\t\texpect(procedureEntity.getNextExpectedEvent()).toBe(\"event_1\");\r\n\t\tprocedureEntity.recordUserEvent(\"event_1\");\r\n\t\texpect(procedureEntity.getNextExpectedEvent()).toBe(\"event_2\");\r\n\t});\r\n\r\n\tit(\"provides next unemitted event for unordered procedures with hints enabled\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.addEventId(\"event_2\");\r\n\t\tprocedureEntity.addEventId(\"event_3\");\r\n\t\tprocedureEntity.setOrderMatters(false);\r\n\t\tprocedureEntity.setShowHints(true);\r\n\t\texpect(procedureEntity.getNextExpectedEvent()).toBe(\"event_1\");\r\n\t\tprocedureEntity.recordUserEvent(\"event_3\");\r\n\t\texpect(procedureEntity.getNextExpectedEvent()).toBe(\"event_1\");\r\n\t\tprocedureEntity.recordUserEvent(\"event_1\");\r\n\t\texpect(procedureEntity.getNextExpectedEvent()).toBe(\"event_2\");\r\n\t});\r\n\r\n\tit(\"returns null when hints are disabled\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.setShowHints(false);\r\n\t\texpect(procedureEntity.getNextExpectedEvent()).toBe(null);\r\n\t});\r\n\r\n\tit(\"can toggle order matters setting\", () => {\r\n\t\texpect(procedureEntity.orderMatters).toBe(true);\r\n\t\tprocedureEntity.setOrderMatters(false);\r\n\t\texpect(procedureEntity.orderMatters).toBe(false);\r\n\t});\r\n\r\n\tit(\"can toggle hints setting\", () => {\r\n\t\texpect(procedureEntity.showHints).toBe(true);\r\n\t\tprocedureEntity.setShowHints(false);\r\n\t\texpect(procedureEntity.showHints).toBe(false);\r\n\t});\r\n\r\n\tit(\"can toggle quiz mode\", () => {\r\n\t\texpect(procedureEntity.isQuiz).toBe(false);\r\n\t\tprocedureEntity.setIsQuiz(true);\r\n\t\texpect(procedureEntity.isQuiz).toBe(true);\r\n\t});\r\n\r\n\tit(\"resets user progress while preserving configuration\", () => {\r\n\t\tprocedureEntity.addEventId(\"event_1\");\r\n\t\tprocedureEntity.addEventId(\"event_2\");\r\n\t\tprocedureEntity.setOrderMatters(false);\r\n\t\tprocedureEntity.setShowHints(false);\r\n\t\tprocedureEntity.setIsQuiz(true);\r\n\t\tprocedureEntity.recordUserEvent(\"event_1\");\r\n\t\texpect(procedureEntity.userEventLog.length).toBe(1);\r\n\t\tprocedureEntity.reset();\r\n\t\texpect(procedureEntity.userEventLog).toEqual([]);\r\n\t\texpect(procedureEntity.currentStepIndex).toBe(0);\r\n\t\texpect(procedureEntity.validationMessage).toBe(null);\r\n\t\texpect(procedureEntity.eventIds).toEqual([\"event_1\", \"event_2\"]);\r\n\t\texpect(procedureEntity.orderMatters).toBe(false);\r\n\t\texpect(procedureEntity.showHints).toBe(false);\r\n\t\texpect(procedureEntity.isQuiz).toBe(true);\r\n\t});\r\n\r\n\tdescribe(\"recordUserEvent revisits (order matters)\", () => {\r\n\t\tbeforeEach(() => {\r\n\t\t\tprocedureEntity.addEventId(\"s1\");\r\n\t\t\tprocedureEntity.addEventId(\"s2\");\r\n\t\t\tprocedureEntity.addEventId(\"s3\");\r\n\t\t\tprocedureEntity.setOrderMatters(true);\r\n\t\t});\r\n\r\n\t\tit(\"does not log a re-emission of an already-completed step\", () => {\r\n\t\t\tprocedureEntity.recordUserEvent(\"s1\");\r\n\t\t\tprocedureEntity.recordUserEvent(\"s2\");\r\n\t\t\tprocedureEntity.recordUserEvent(\"s1\");\r\n\t\t\texpect(procedureEntity.userEventLog).toEqual([\"s1\", \"s2\"]);\r\n\t\t\texpect(procedureEntity.currentStepIndex).toBe(2);\r\n\t\t});\r\n\r\n\t\tit(\"does not set a validation message for a benign revisit\", () => {\r\n\t\t\tprocedureEntity.recordUserEvent(\"s1\");\r\n\t\t\tprocedureEntity.recordUserEvent(\"s1\");\r\n\t\t\texpect(procedureEntity.validationMessage).toBeNull();\r\n\t\t});\r\n\r\n\t\tit(\"still logs and flags an early emission of a later step\", () => {\r\n\t\t\tprocedureEntity.recordUserEvent(\"s1\");\r\n\t\t\tprocedureEntity.recordUserEvent(\"s3\");\r\n\t\t\texpect(procedureEntity.userEventLog).toEqual([\"s1\", \"s3\"]);\r\n\t\t\texpect(procedureEntity.validationMessage).toBe(\r\n\t\t\t\t\"Expected 's2', but got 's3'\",\r\n\t\t\t);\r\n\t\t\texpect(procedureEntity.currentStepIndex).toBe(1);\r\n\t\t});\r\n\t});\r\n\r\n\tdescribe(\"calculateScore (order matters, 10 steps)\", () => {\r\n\t\tconst steps = [\r\n\t\t\t\"s1\",\r\n\t\t\t\"s2\",\r\n\t\t\t\"s3\",\r\n\t\t\t\"s4\",\r\n\t\t\t\"s5\",\r\n\t\t\t\"s6\",\r\n\t\t\t\"s7\",\r\n\t\t\t\"s8\",\r\n\t\t\t\"s9\",\r\n\t\t\t\"s10\",\r\n\t\t];\r\n\r\n\t\tconst record = (...ids: string[]) =>\r\n\t\t\tids.forEach((id) => procedureEntity.recordUserEvent(id));\r\n\r\n\t\tconst correctFlags = () =>\r\n\t\t\tprocedureEntity.calculateScore().comparison.map((c) => c.correct);\r\n\r\n\t\tbeforeEach(() => {\r\n\t\t\tsteps.forEach((s) => procedureEntity.addEventId(s));\r\n\t\t\tprocedureEntity.setOrderMatters(true);\r\n\t\t});\r\n\r\n\t\tit(\"scores a perfect run 100% with every step correct\", () => {\r\n\t\t\trecord(...steps);\r\n\t\t\tconst score = procedureEntity.calculateScore();\r\n\t\t\texpect(score.percentage).toBe(100);\r\n\t\t\texpect(score.comparison.map((c) => c.eventId)).toEqual(steps);\r\n\t\t\texpect(correctFlags()).toEqual(new Array(10).fill(true));\r\n\t\t});\r\n\r\n\t\tit(\"does not penalize one extra authored event emitted early\", () => {\r\n\t\t\trecord(\"s1\", \"s7\", \"s2\", \"s3\", \"s4\", \"s5\", \"s6\", \"s7\", \"s8\", \"s9\", \"s10\");\r\n\t\t\texpect(procedureEntity.calculateScore().percentage).toBe(100);\r\n\t\t\texpect(correctFlags()).toEqual(new Array(10).fill(true));\r\n\t\t});\r\n\r\n\t\tit(\"scores a skipped step 90% and marks only that step incorrect\", () => {\r\n\t\t\trecord(\"s1\", \"s2\", \"s3\", \"s4\", \"s6\", \"s7\", \"s8\", \"s9\", \"s10\");\r\n\t\t\texpect(procedureEntity.calculateScore().percentage).toBe(90);\r\n\t\t\texpect(correctFlags()).toEqual([\r\n\t\t\t\ttrue,\r\n\t\t\t\ttrue,\r\n\t\t\t\ttrue,\r\n\t\t\t\ttrue,\r\n\t\t\t\tfalse,\r\n\t\t\t\ttrue,\r\n\t\t\t\ttrue,\r\n\t\t\t\ttrue,\r\n\t\t\t\ttrue,\r\n\t\t\t\ttrue,\r\n\t\t\t]);\r\n\t\t});\r\n\r\n\t\tit(\"scores swapped steps 90%, keeping the earlier expected step (deterministic tie-break)\", () => {\r\n\t\t\trecord(\"s1\", \"s2\", \"s3\", \"s5\", \"s4\", \"s6\", \"s7\", \"s8\", \"s9\", \"s10\");\r\n\t\t\tfor (let run = 0; run < 3; run++) {\r\n\t\t\t\tconst score = procedureEntity.calculateScore();\r\n\t\t\t\texpect(score.percentage).toBe(90);\r\n\t\t\t\texpect(score.comparison[3].correct).toBe(true);\r\n\t\t\t\texpect(score.comparison[4].correct).toBe(false);\r\n\t\t\t\texpect(score.comparison.filter((c) => c.correct).length).toBe(9);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tit(\"scores a repeated first step 100% with no duplicate in the log\", () => {\r\n\t\t\trecord(\"s1\", \"s1\", \"s2\", \"s3\", \"s4\", \"s5\", \"s6\", \"s7\", \"s8\", \"s9\", \"s10\");\r\n\t\t\texpect(procedureEntity.userEventLog).toEqual(steps);\r\n\t\t\texpect(procedureEntity.validationMessage).toBeNull();\r\n\t\t\texpect(procedureEntity.calculateScore().percentage).toBe(100);\r\n\t\t\texpect(correctFlags()).toEqual(new Array(10).fill(true));\r\n\t\t});\r\n\r\n\t\tit(\"scores a fully reversed run 10%\", () => {\r\n\t\t\trecord(...[...steps].reverse());\r\n\t\t\tconst score = procedureEntity.calculateScore();\r\n\t\t\texpect(score.percentage).toBe(10);\r\n\t\t\texpect(score.comparison[0].correct).toBe(true);\r\n\t\t\texpect(score.comparison.filter((c) => c.correct).length).toBe(1);\r\n\t\t});\r\n\r\n\t\tit(\"scores an empty log 0% with every step incorrect\", () => {\r\n\t\t\tconst score = procedureEntity.calculateScore();\r\n\t\t\texpect(score.percentage).toBe(0);\r\n\t\t\texpect(correctFlags()).toEqual(new Array(10).fill(false));\r\n\t\t\tscore.comparison.forEach((c) => {\r\n\t\t\t\texpect(c.expected).toBe(true);\r\n\t\t\t\texpect(c.actual).toBe(false);\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\tit(\"keeps the comparison shape { eventId, expected, actual, correct }\", () => {\r\n\t\t\trecord(\"s1\", \"s2\", \"s3\", \"s4\", \"s6\", \"s7\", \"s8\", \"s9\", \"s10\");\r\n\t\t\tconst skipped = procedureEntity.calculateScore().comparison[4];\r\n\t\t\texpect(skipped).toEqual({\r\n\t\t\t\teventId: \"s5\",\r\n\t\t\t\texpected: true,\r\n\t\t\t\tactual: false,\r\n\t\t\t\tcorrect: false,\r\n\t\t\t});\r\n\t\t});\r\n\t});\r\n\r\n\tdescribe(\"calculateScore edge cases\", () => {\r\n\t\tit(\"returns { percentage: 0, comparison: [] } for an empty procedure\", () => {\r\n\t\t\tprocedureEntity.setOrderMatters(true);\r\n\t\t\texpect(procedureEntity.calculateScore()).toEqual({\r\n\t\t\t\tpercentage: 0,\r\n\t\t\t\tcomparison: [],\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\tit(\"keeps set-based scoring when order does not matter\", () => {\r\n\t\t\tprocedureEntity.addEventId(\"a\");\r\n\t\t\tprocedureEntity.addEventId(\"b\");\r\n\t\t\tprocedureEntity.addEventId(\"c\");\r\n\t\t\tprocedureEntity.setOrderMatters(false);\r\n\t\t\tprocedureEntity.recordUserEvent(\"c\");\r\n\t\t\tprocedureEntity.recordUserEvent(\"a\");\r\n\t\t\tconst score = procedureEntity.calculateScore();\r\n\t\t\texpect(score.percentage).toBe(67);\r\n\t\t\texpect(score.comparison.map((c) => c.correct)).toEqual([\r\n\t\t\t\ttrue,\r\n\t\t\t\tfalse,\r\n\t\t\t\ttrue,\r\n\t\t\t]);\r\n\t\t});\r\n\t});\r\n\r\n\tdescribe(\"event category lookup (#53)\", () => {\r\n\t\tit(\"treats every step as assessed when no lookup is injected\", () => {\r\n\t\t\texpect(procedureEntity.getEventCategory(\"navigate-to-overhead\")).toBe(\r\n\t\t\t\t\"assessed\",\r\n\t\t\t);\r\n\t\t});\r\n\r\n\t\tit(\"resolves a step's category through the injected lookup at call time\", () => {\r\n\t\t\tprocedureEntity.setEventCategoryLookup((eventId) =>\r\n\t\t\t\teventId === \"navigate-to-overhead\" ? \"instructional\" : \"assessed\",\r\n\t\t\t);\r\n\r\n\t\t\texpect(procedureEntity.getEventCategory(\"navigate-to-overhead\")).toBe(\r\n\t\t\t\t\"instructional\",\r\n\t\t\t);\r\n\t\t\texpect(procedureEntity.getEventCategory(\"lever\")).toBe(\"assessed\");\r\n\t\t});\r\n\r\n\t\tit(\"notifies observers when the lookup is injected so presenters rebuild\", () => {\r\n\t\t\tconst observer = jest.fn();\r\n\t\t\tprocedureEntity.addChangeObserver(observer);\r\n\r\n\t\t\tprocedureEntity.setEventCategoryLookup(() => \"assessed\");\r\n\r\n\t\t\texpect(observer).toHaveBeenCalledTimes(1);\r\n\t\t});\r\n\t});\r\n\r\n\tdescribe(\"quiz mode with instructional steps (#53)\", () => {\r\n\t\tconst NAV = \"navigate-to-overhead\";\r\n\r\n\t\tbeforeEach(() => {\r\n\t\t\tprocedureEntity.setEventCategoryLookup((eventId) =>\r\n\t\t\t\teventId === NAV ? \"instructional\" : \"assessed\",\r\n\t\t\t);\r\n\t\t\tprocedureEntity.addEventId(NAV);\r\n\t\t\tprocedureEntity.addEventId(\"lever\");\r\n\t\t\tprocedureEntity.addEventId(\"valve\");\r\n\t\t\tprocedureEntity.setIsQuiz(true);\r\n\t\t});\r\n\r\n\t\tit(\"scores only the assessed subsequence\", () => {\r\n\t\t\tprocedureEntity.recordUserEvent(\"lever\");\r\n\t\t\tprocedureEntity.recordUserEvent(\"valve\");\r\n\r\n\t\t\texpect(procedureEntity.calculateScore()).toEqual({\r\n\t\t\t\tpercentage: 100,\r\n\t\t\t\tcomparison: [\r\n\t\t\t\t\t{ eventId: \"lever\", expected: true, actual: true, correct: true },\r\n\t\t\t\t\t{ eventId: \"valve\", expected: true, actual: true, correct: true },\r\n\t\t\t\t],\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\tit(\"logs an instructional emission without advancing or flagging the attempt\", () => {\r\n\t\t\tprocedureEntity.recordUserEvent(NAV);\r\n\r\n\t\t\texpect(procedureEntity.userEventLog).toEqual([NAV]);\r\n\t\t\texpect(procedureEntity.currentStepIndex).toBe(0);\r\n\t\t\texpect(procedureEntity.validationMessage).toBeNull();\r\n\t\t\texpect(procedureEntity.getNextExpectedEvent()).toBe(\"lever\");\r\n\t\t});\r\n\r\n\t\tit(\"does not misalign later assessed steps around an instructional emission\", () => {\r\n\t\t\tprocedureEntity.recordUserEvent(\"lever\");\r\n\t\t\tprocedureEntity.recordUserEvent(NAV);\r\n\t\t\tprocedureEntity.recordUserEvent(\"valve\");\r\n\r\n\t\t\texpect(procedureEntity.isComplete).toBe(true);\r\n\t\t\texpect(procedureEntity.getProgressPercentage()).toBe(100);\r\n\t\t\texpect(procedureEntity.calculateScore().percentage).toBe(100);\r\n\t\t});\r\n\r\n\t\tit(\"treats a quiz made only of instructional steps like an empty procedure\", () => {\r\n\t\t\tprocedureEntity.removeEventId(\"lever\");\r\n\t\t\tprocedureEntity.removeEventId(\"valve\");\r\n\r\n\t\t\tprocedureEntity.recordUserEvent(NAV);\r\n\r\n\t\t\texpect(procedureEntity.isComplete).toBe(false);\r\n\t\t\texpect(procedureEntity.getProgressPercentage()).toBe(0);\r\n\t\t\texpect(procedureEntity.getNextExpectedEvent()).toBeNull();\r\n\t\t\texpect(procedureEntity.calculateScore()).toEqual({\r\n\t\t\t\tpercentage: 0,\r\n\t\t\t\tcomparison: [],\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\tit(\"ignores categories entirely in training mode\", () => {\r\n\t\t\tprocedureEntity.setIsQuiz(false);\r\n\r\n\t\t\tprocedureEntity.recordUserEvent(NAV);\r\n\t\t\texpect(procedureEntity.currentStepIndex).toBe(1);\r\n\t\t\texpect(procedureEntity.getProgressPercentage()).toBe(33);\r\n\r\n\t\t\tprocedureEntity.recordUserEvent(\"lever\");\r\n\t\t\tprocedureEntity.recordUserEvent(\"valve\");\r\n\t\t\texpect(procedureEntity.isComplete).toBe(true);\r\n\t\t\texpect(procedureEntity.calculateScore().comparison).toHaveLength(3);\r\n\t\t});\r\n\r\n\t\tit(\"logs a repeated instructional emission only once, however often the student revisits\", () => {\r\n\t\t\tprocedureEntity.recordUserEvent(NAV);\r\n\t\t\tprocedureEntity.recordUserEvent(\"lever\");\r\n\t\t\tprocedureEntity.recordUserEvent(NAV);\r\n\t\t\tprocedureEntity.recordUserEvent(NAV);\r\n\r\n\t\t\texpect(procedureEntity.userEventLog).toEqual([NAV, \"lever\"]);\r\n\t\t\t// The bounded log never changes the assessed score.\r\n\t\t\texpect(procedureEntity.calculateScore().percentage).toBe(50);\r\n\t\t});\r\n\r\n\t\tit(\"flags a quiz whose steps are all instructional as needing an assessed step\", () => {\r\n\t\t\tprocedureEntity.removeEventId(\"lever\");\r\n\t\t\tprocedureEntity.removeEventId(\"valve\");\r\n\r\n\t\t\texpect(procedureEntity.getAuthoringValidationMessage()).toBe(\r\n\t\t\t\t\"A quiz needs at least one assessed step\",\r\n\t\t\t);\r\n\t\t\texpect(procedureEntity.validateProgress()).toBe(\r\n\t\t\t\t\"A quiz needs at least one assessed step\",\r\n\t\t\t);\r\n\t\t});\r\n\r\n\t\tit(\"does not flag a quiz that has assessed steps, nor an all-instructional training procedure\", () => {\r\n\t\t\t// The mixed quiz has assessed steps → no authoring message.\r\n\t\t\texpect(procedureEntity.getAuthoringValidationMessage()).toBeNull();\r\n\r\n\t\t\t// All-instructional, but training mode is never a quiz problem.\r\n\t\t\tprocedureEntity.removeEventId(\"lever\");\r\n\t\t\tprocedureEntity.removeEventId(\"valve\");\r\n\t\t\tprocedureEntity.setIsQuiz(false);\r\n\t\t\texpect(procedureEntity.getAuthoringValidationMessage()).toBeNull();\r\n\t\t});\r\n\t});\r\n});\r\n"]}
1
+ {"version":3,"file":"ProcedureEntity.test.js","sourceRoot":"","sources":["../../../../src/Procedure/Entities/ProcedureEntity.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { AppObjectRepo, makeAppObjectRepo } from \"@vived/core\";\nimport { ProcedureEntity, makeProcedureEntity } from \"./ProcedureEntity\";\n\ndescribe(\"ProcedureEntity\", () => {\n let appObjects: AppObjectRepo;\n let procedureEntity: ProcedureEntity;\n\n beforeEach(() => {\n appObjects = makeAppObjectRepo();\n const appObject = appObjects.getOrCreate(\"TestProcedure\");\n procedureEntity = makeProcedureEntity(appObject);\n });\n\n it(\"implements Challenge interface correctly\", () => {\n expect(procedureEntity.challengeID).toBe(\"PROCEDURE\");\n expect(procedureEntity.name).toBe(\"Procedure\");\n expect(typeof procedureEntity.consumerHelpText).toBe(\"string\");\n expect(typeof procedureEntity.authorHelpText).toBe(\"string\");\n expect(typeof procedureEntity.reset).toBe(\"function\");\n });\n\n it(\"has dynamic helpHeading based on quiz mode\", () => {\n expect(procedureEntity.helpHeading).toBe(\"Procedure Training\");\n procedureEntity.setIsQuiz(true);\n expect(procedureEntity.helpHeading).toBe(\"Procedure Challenge\");\n procedureEntity.setIsQuiz(false);\n expect(procedureEntity.helpHeading).toBe(\"Procedure Training\");\n });\n\n it(\"has dynamic consumerHelpText based on quiz mode\", () => {\n expect(procedureEntity.consumerHelpText).toBe(\n \"Follow the steps in order to complete the training procedure.\",\n );\n procedureEntity.setIsQuiz(true);\n expect(procedureEntity.consumerHelpText).toBe(\n \"Complete the procedure challenge on your own and get scored after submitting.\",\n );\n procedureEntity.setIsQuiz(false);\n expect(procedureEntity.consumerHelpText).toBe(\n \"Follow the steps in order to complete the training procedure.\",\n );\n });\n\n it(\"has correct singleton registration\", () => {\n const retrieved = ProcedureEntity.get(appObjects);\n expect(retrieved).toBe(procedureEntity);\n });\n\n it(\"starts with empty event list\", () => {\n expect(procedureEntity.eventIds).toEqual([]);\n });\n\n it(\"can add events to procedure\", () => {\n procedureEntity.addEventId(\"test_event_1\");\n procedureEntity.addEventId(\"test_event_2\");\n expect(procedureEntity.eventIds).toEqual([\"test_event_1\", \"test_event_2\"]);\n });\n\n it(\"prevents duplicate events\", () => {\n procedureEntity.addEventId(\"test_event\");\n procedureEntity.addEventId(\"test_event\");\n expect(procedureEntity.eventIds).toEqual([\"test_event\"]);\n expect(procedureEntity.validationMessage).toContain(\n \"already in the procedure\",\n );\n });\n\n it(\"can remove events from procedure\", () => {\n procedureEntity.addEventId(\"test_event_1\");\n procedureEntity.addEventId(\"test_event_2\");\n procedureEntity.removeEventId(\"test_event_1\");\n expect(procedureEntity.eventIds).toEqual([\"test_event_2\"]);\n });\n\n it(\"handles removing non-existent events\", () => {\n procedureEntity.removeEventId(\"non_existent\");\n expect(procedureEntity.validationMessage).toContain(\"not in the procedure\");\n });\n\n it(\"can clear all events\", () => {\n procedureEntity.addEventId(\"test_event_1\");\n procedureEntity.addEventId(\"test_event_2\");\n procedureEntity.clearEventIds();\n expect(procedureEntity.eventIds).toEqual([]);\n });\n\n it(\"starts with empty user event log\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.addEventId(\"event_2\");\n procedureEntity.addEventId(\"event_3\");\n expect(procedureEntity.userEventLog).toEqual([]);\n expect(procedureEntity.currentStepIndex).toBe(0);\n expect(procedureEntity.isComplete).toBe(false);\n });\n\n it(\"records user events for ordered procedures\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.addEventId(\"event_2\");\n procedureEntity.addEventId(\"event_3\");\n procedureEntity.setOrderMatters(true);\n procedureEntity.recordUserEvent(\"event_1\");\n expect(procedureEntity.userEventLog).toEqual([\"event_1\"]);\n expect(procedureEntity.currentStepIndex).toBe(1);\n procedureEntity.recordUserEvent(\"event_2\");\n expect(procedureEntity.currentStepIndex).toBe(2);\n });\n\n it(\"validates order in ordered procedures\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.addEventId(\"event_2\");\n procedureEntity.addEventId(\"event_3\");\n procedureEntity.setOrderMatters(true);\n procedureEntity.recordUserEvent(\"event_2\");\n expect(procedureEntity.validationMessage).toContain(\n \"Expected 'event_1', but got 'event_2'\",\n );\n expect(procedureEntity.currentStepIndex).toBe(0);\n });\n\n it(\"ignores order in unordered procedures\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.addEventId(\"event_2\");\n procedureEntity.addEventId(\"event_3\");\n procedureEntity.setOrderMatters(false);\n procedureEntity.recordUserEvent(\"event_3\");\n procedureEntity.recordUserEvent(\"event_1\");\n expect(procedureEntity.userEventLog).toEqual([\"event_3\", \"event_1\"]);\n });\n\n it(\"ignores events not in procedure\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.addEventId(\"event_2\");\n procedureEntity.addEventId(\"event_3\");\n procedureEntity.recordUserEvent(\"unknown_event\");\n expect(procedureEntity.userEventLog).toEqual([]);\n });\n\n it(\"detects completion in ordered procedures\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.addEventId(\"event_2\");\n procedureEntity.setOrderMatters(true);\n expect(procedureEntity.isComplete).toBe(false);\n procedureEntity.recordUserEvent(\"event_1\");\n expect(procedureEntity.isComplete).toBe(false);\n procedureEntity.recordUserEvent(\"event_2\");\n expect(procedureEntity.isComplete).toBe(true);\n });\n\n it(\"detects completion in unordered procedures\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.addEventId(\"event_2\");\n procedureEntity.setOrderMatters(false);\n expect(procedureEntity.isComplete).toBe(false);\n procedureEntity.recordUserEvent(\"event_2\");\n expect(procedureEntity.isComplete).toBe(false);\n procedureEntity.recordUserEvent(\"event_1\");\n expect(procedureEntity.isComplete).toBe(true);\n });\n\n it(\"returns false for empty procedures\", () => {\n procedureEntity.clearEventIds();\n expect(procedureEntity.isComplete).toBe(false);\n });\n\n it(\"calculates progress for ordered procedures\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.addEventId(\"event_2\");\n procedureEntity.addEventId(\"event_3\");\n procedureEntity.addEventId(\"event_4\");\n procedureEntity.setOrderMatters(true);\n expect(procedureEntity.getProgressPercentage()).toBe(0);\n procedureEntity.recordUserEvent(\"event_1\");\n expect(procedureEntity.getProgressPercentage()).toBe(25);\n procedureEntity.recordUserEvent(\"event_2\");\n expect(procedureEntity.getProgressPercentage()).toBe(50);\n procedureEntity.recordUserEvent(\"event_3\");\n procedureEntity.recordUserEvent(\"event_4\");\n expect(procedureEntity.getProgressPercentage()).toBe(100);\n });\n\n it(\"calculates progress for unordered procedures\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.addEventId(\"event_2\");\n procedureEntity.addEventId(\"event_3\");\n procedureEntity.addEventId(\"event_4\");\n procedureEntity.setOrderMatters(false);\n expect(procedureEntity.getProgressPercentage()).toBe(0);\n procedureEntity.recordUserEvent(\"event_3\");\n expect(procedureEntity.getProgressPercentage()).toBe(25);\n procedureEntity.recordUserEvent(\"event_1\");\n expect(procedureEntity.getProgressPercentage()).toBe(50);\n });\n\n it(\"provides next expected event for ordered procedures with hints enabled\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.addEventId(\"event_2\");\n procedureEntity.addEventId(\"event_3\");\n procedureEntity.setOrderMatters(true);\n procedureEntity.setShowHints(true);\n expect(procedureEntity.getNextExpectedEvent()).toBe(\"event_1\");\n procedureEntity.recordUserEvent(\"event_1\");\n expect(procedureEntity.getNextExpectedEvent()).toBe(\"event_2\");\n });\n\n it(\"provides next unemitted event for unordered procedures with hints enabled\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.addEventId(\"event_2\");\n procedureEntity.addEventId(\"event_3\");\n procedureEntity.setOrderMatters(false);\n procedureEntity.setShowHints(true);\n expect(procedureEntity.getNextExpectedEvent()).toBe(\"event_1\");\n procedureEntity.recordUserEvent(\"event_3\");\n expect(procedureEntity.getNextExpectedEvent()).toBe(\"event_1\");\n procedureEntity.recordUserEvent(\"event_1\");\n expect(procedureEntity.getNextExpectedEvent()).toBe(\"event_2\");\n });\n\n it(\"returns null when hints are disabled\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.setShowHints(false);\n expect(procedureEntity.getNextExpectedEvent()).toBe(null);\n });\n\n it(\"can toggle order matters setting\", () => {\n expect(procedureEntity.orderMatters).toBe(true);\n procedureEntity.setOrderMatters(false);\n expect(procedureEntity.orderMatters).toBe(false);\n });\n\n it(\"can toggle hints setting\", () => {\n expect(procedureEntity.showHints).toBe(true);\n procedureEntity.setShowHints(false);\n expect(procedureEntity.showHints).toBe(false);\n });\n\n it(\"can toggle quiz mode\", () => {\n expect(procedureEntity.isQuiz).toBe(false);\n procedureEntity.setIsQuiz(true);\n expect(procedureEntity.isQuiz).toBe(true);\n });\n\n it(\"resets user progress while preserving configuration\", () => {\n procedureEntity.addEventId(\"event_1\");\n procedureEntity.addEventId(\"event_2\");\n procedureEntity.setOrderMatters(false);\n procedureEntity.setShowHints(false);\n procedureEntity.setIsQuiz(true);\n procedureEntity.recordUserEvent(\"event_1\");\n expect(procedureEntity.userEventLog.length).toBe(1);\n procedureEntity.reset();\n expect(procedureEntity.userEventLog).toEqual([]);\n expect(procedureEntity.currentStepIndex).toBe(0);\n expect(procedureEntity.validationMessage).toBe(null);\n expect(procedureEntity.eventIds).toEqual([\"event_1\", \"event_2\"]);\n expect(procedureEntity.orderMatters).toBe(false);\n expect(procedureEntity.showHints).toBe(false);\n expect(procedureEntity.isQuiz).toBe(true);\n });\n\n describe(\"recordUserEvent revisits (order matters)\", () => {\n beforeEach(() => {\n procedureEntity.addEventId(\"s1\");\n procedureEntity.addEventId(\"s2\");\n procedureEntity.addEventId(\"s3\");\n procedureEntity.setOrderMatters(true);\n });\n\n it(\"does not log a re-emission of an already-completed step\", () => {\n procedureEntity.recordUserEvent(\"s1\");\n procedureEntity.recordUserEvent(\"s2\");\n procedureEntity.recordUserEvent(\"s1\");\n expect(procedureEntity.userEventLog).toEqual([\"s1\", \"s2\"]);\n expect(procedureEntity.currentStepIndex).toBe(2);\n });\n\n it(\"does not set a validation message for a benign revisit\", () => {\n procedureEntity.recordUserEvent(\"s1\");\n procedureEntity.recordUserEvent(\"s1\");\n expect(procedureEntity.validationMessage).toBeNull();\n });\n\n it(\"still logs and flags an early emission of a later step\", () => {\n procedureEntity.recordUserEvent(\"s1\");\n procedureEntity.recordUserEvent(\"s3\");\n expect(procedureEntity.userEventLog).toEqual([\"s1\", \"s3\"]);\n expect(procedureEntity.validationMessage).toBe(\n \"Expected 's2', but got 's3'\",\n );\n expect(procedureEntity.currentStepIndex).toBe(1);\n });\n });\n\n describe(\"calculateScore (order matters, 10 steps)\", () => {\n const steps = [\"s1\", \"s2\", \"s3\", \"s4\", \"s5\", \"s6\", \"s7\", \"s8\", \"s9\", \"s10\"];\n\n const record = (...ids: string[]) =>\n ids.forEach((id) => procedureEntity.recordUserEvent(id));\n\n const correctFlags = () =>\n procedureEntity.calculateScore().comparison.map((c) => c.correct);\n\n beforeEach(() => {\n steps.forEach((s) => procedureEntity.addEventId(s));\n procedureEntity.setOrderMatters(true);\n });\n\n it(\"scores a perfect run 100% with every step correct\", () => {\n record(...steps);\n const score = procedureEntity.calculateScore();\n expect(score.percentage).toBe(100);\n expect(score.comparison.map((c) => c.eventId)).toEqual(steps);\n expect(correctFlags()).toEqual(new Array(10).fill(true));\n });\n\n it(\"does not penalize one extra authored event emitted early\", () => {\n record(\"s1\", \"s7\", \"s2\", \"s3\", \"s4\", \"s5\", \"s6\", \"s7\", \"s8\", \"s9\", \"s10\");\n expect(procedureEntity.calculateScore().percentage).toBe(100);\n expect(correctFlags()).toEqual(new Array(10).fill(true));\n });\n\n it(\"scores a skipped step 90% and marks only that step incorrect\", () => {\n record(\"s1\", \"s2\", \"s3\", \"s4\", \"s6\", \"s7\", \"s8\", \"s9\", \"s10\");\n expect(procedureEntity.calculateScore().percentage).toBe(90);\n expect(correctFlags()).toEqual([\n true,\n true,\n true,\n true,\n false,\n true,\n true,\n true,\n true,\n true,\n ]);\n });\n\n it(\"scores swapped steps 90%, keeping the earlier expected step (deterministic tie-break)\", () => {\n record(\"s1\", \"s2\", \"s3\", \"s5\", \"s4\", \"s6\", \"s7\", \"s8\", \"s9\", \"s10\");\n for (let run = 0; run < 3; run++) {\n const score = procedureEntity.calculateScore();\n expect(score.percentage).toBe(90);\n expect(score.comparison[3].correct).toBe(true);\n expect(score.comparison[4].correct).toBe(false);\n expect(score.comparison.filter((c) => c.correct).length).toBe(9);\n }\n });\n\n it(\"scores a repeated first step 100% with no duplicate in the log\", () => {\n record(\"s1\", \"s1\", \"s2\", \"s3\", \"s4\", \"s5\", \"s6\", \"s7\", \"s8\", \"s9\", \"s10\");\n expect(procedureEntity.userEventLog).toEqual(steps);\n expect(procedureEntity.validationMessage).toBeNull();\n expect(procedureEntity.calculateScore().percentage).toBe(100);\n expect(correctFlags()).toEqual(new Array(10).fill(true));\n });\n\n it(\"scores a fully reversed run 10%\", () => {\n record(...[...steps].reverse());\n const score = procedureEntity.calculateScore();\n expect(score.percentage).toBe(10);\n expect(score.comparison[0].correct).toBe(true);\n expect(score.comparison.filter((c) => c.correct).length).toBe(1);\n });\n\n it(\"scores an empty log 0% with every step incorrect\", () => {\n const score = procedureEntity.calculateScore();\n expect(score.percentage).toBe(0);\n expect(correctFlags()).toEqual(new Array(10).fill(false));\n score.comparison.forEach((c) => {\n expect(c.expected).toBe(true);\n expect(c.actual).toBe(false);\n });\n });\n\n it(\"keeps the comparison shape { eventId, expected, actual, correct }\", () => {\n record(\"s1\", \"s2\", \"s3\", \"s4\", \"s6\", \"s7\", \"s8\", \"s9\", \"s10\");\n const skipped = procedureEntity.calculateScore().comparison[4];\n expect(skipped).toEqual({\n eventId: \"s5\",\n expected: true,\n actual: false,\n correct: false,\n });\n });\n });\n\n describe(\"calculateScore edge cases\", () => {\n it(\"returns { percentage: 0, comparison: [] } for an empty procedure\", () => {\n procedureEntity.setOrderMatters(true);\n expect(procedureEntity.calculateScore()).toEqual({\n percentage: 0,\n comparison: [],\n });\n });\n\n it(\"keeps set-based scoring when order does not matter\", () => {\n procedureEntity.addEventId(\"a\");\n procedureEntity.addEventId(\"b\");\n procedureEntity.addEventId(\"c\");\n procedureEntity.setOrderMatters(false);\n procedureEntity.recordUserEvent(\"c\");\n procedureEntity.recordUserEvent(\"a\");\n const score = procedureEntity.calculateScore();\n expect(score.percentage).toBe(67);\n expect(score.comparison.map((c) => c.correct)).toEqual([\n true,\n false,\n true,\n ]);\n });\n });\n\n describe(\"event category lookup (#53)\", () => {\n it(\"treats every step as assessed when no lookup is injected\", () => {\n expect(procedureEntity.getEventCategory(\"navigate-to-overhead\")).toBe(\n \"assessed\",\n );\n });\n\n it(\"resolves a step's category through the injected lookup at call time\", () => {\n procedureEntity.setEventCategoryLookup((eventId) =>\n eventId === \"navigate-to-overhead\" ? \"instructional\" : \"assessed\",\n );\n\n expect(procedureEntity.getEventCategory(\"navigate-to-overhead\")).toBe(\n \"instructional\",\n );\n expect(procedureEntity.getEventCategory(\"lever\")).toBe(\"assessed\");\n });\n\n it(\"notifies observers when the lookup is injected so presenters rebuild\", () => {\n const observer = jest.fn();\n procedureEntity.addChangeObserver(observer);\n\n procedureEntity.setEventCategoryLookup(() => \"assessed\");\n\n expect(observer).toHaveBeenCalledTimes(1);\n });\n });\n\n describe(\"quiz mode with instructional steps (#53)\", () => {\n const NAV = \"navigate-to-overhead\";\n\n beforeEach(() => {\n procedureEntity.setEventCategoryLookup((eventId) =>\n eventId === NAV ? \"instructional\" : \"assessed\",\n );\n procedureEntity.addEventId(NAV);\n procedureEntity.addEventId(\"lever\");\n procedureEntity.addEventId(\"valve\");\n procedureEntity.setIsQuiz(true);\n });\n\n it(\"scores only the assessed subsequence\", () => {\n procedureEntity.recordUserEvent(\"lever\");\n procedureEntity.recordUserEvent(\"valve\");\n\n expect(procedureEntity.calculateScore()).toEqual({\n percentage: 100,\n comparison: [\n { eventId: \"lever\", expected: true, actual: true, correct: true },\n { eventId: \"valve\", expected: true, actual: true, correct: true },\n ],\n });\n });\n\n it(\"logs an instructional emission without advancing or flagging the attempt\", () => {\n procedureEntity.recordUserEvent(NAV);\n\n expect(procedureEntity.userEventLog).toEqual([NAV]);\n expect(procedureEntity.currentStepIndex).toBe(0);\n expect(procedureEntity.validationMessage).toBeNull();\n expect(procedureEntity.getNextExpectedEvent()).toBe(\"lever\");\n });\n\n it(\"does not misalign later assessed steps around an instructional emission\", () => {\n procedureEntity.recordUserEvent(\"lever\");\n procedureEntity.recordUserEvent(NAV);\n procedureEntity.recordUserEvent(\"valve\");\n\n expect(procedureEntity.isComplete).toBe(true);\n expect(procedureEntity.getProgressPercentage()).toBe(100);\n expect(procedureEntity.calculateScore().percentage).toBe(100);\n });\n\n it(\"treats a quiz made only of instructional steps like an empty procedure\", () => {\n procedureEntity.removeEventId(\"lever\");\n procedureEntity.removeEventId(\"valve\");\n\n procedureEntity.recordUserEvent(NAV);\n\n expect(procedureEntity.isComplete).toBe(false);\n expect(procedureEntity.getProgressPercentage()).toBe(0);\n expect(procedureEntity.getNextExpectedEvent()).toBeNull();\n expect(procedureEntity.calculateScore()).toEqual({\n percentage: 0,\n comparison: [],\n });\n });\n\n it(\"ignores categories entirely in training mode\", () => {\n procedureEntity.setIsQuiz(false);\n\n procedureEntity.recordUserEvent(NAV);\n expect(procedureEntity.currentStepIndex).toBe(1);\n expect(procedureEntity.getProgressPercentage()).toBe(33);\n\n procedureEntity.recordUserEvent(\"lever\");\n procedureEntity.recordUserEvent(\"valve\");\n expect(procedureEntity.isComplete).toBe(true);\n expect(procedureEntity.calculateScore().comparison).toHaveLength(3);\n });\n\n it(\"logs a repeated instructional emission only once, however often the student revisits\", () => {\n procedureEntity.recordUserEvent(NAV);\n procedureEntity.recordUserEvent(\"lever\");\n procedureEntity.recordUserEvent(NAV);\n procedureEntity.recordUserEvent(NAV);\n\n expect(procedureEntity.userEventLog).toEqual([NAV, \"lever\"]);\n // The bounded log never changes the assessed score.\n expect(procedureEntity.calculateScore().percentage).toBe(50);\n });\n\n it(\"flags a quiz whose steps are all instructional as needing an assessed step\", () => {\n procedureEntity.removeEventId(\"lever\");\n procedureEntity.removeEventId(\"valve\");\n\n expect(procedureEntity.getAuthoringValidationMessage()).toBe(\n \"A quiz needs at least one assessed step\",\n );\n expect(procedureEntity.validateProgress()).toBe(\n \"A quiz needs at least one assessed step\",\n );\n });\n\n it(\"does not flag a quiz that has assessed steps, nor an all-instructional training procedure\", () => {\n // The mixed quiz has assessed steps → no authoring message.\n expect(procedureEntity.getAuthoringValidationMessage()).toBeNull();\n\n // All-instructional, but training mode is never a quiz problem.\n procedureEntity.removeEventId(\"lever\");\n procedureEntity.removeEventId(\"valve\");\n procedureEntity.setIsQuiz(false);\n expect(procedureEntity.getAuthoringValidationMessage()).toBeNull();\n });\n });\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/Procedure/Entities/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,iDAA+B","sourcesContent":["export * from \"./ProcedureEntity\";\r\nexport * from \"./HintRegistry\";\r\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/Procedure/Entities/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,iDAA+B","sourcesContent":["export * from \"./ProcedureEntity\";\nexport * from \"./HintRegistry\";\n"]}