@vue-skuilder/platform-ui 0.2.35 → 0.2.36

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 (189) hide show
  1. package/dist/assets/{About-BWM7KlDK.js → About-74htcNLT.js} +2 -2
  2. package/dist/assets/{About-BWM7KlDK.js.map → About-74htcNLT.js.map} +1 -1
  3. package/dist/assets/AdminDashboard-B00qno2M.js +2 -0
  4. package/dist/assets/{AdminDashboard-CO2rxkF5.js.map → AdminDashboard-B00qno2M.js.map} +1 -1
  5. package/dist/assets/AdminLearner-SJNtSyJ_.js +2 -0
  6. package/dist/assets/{AdminLearner-CZO2Hlk1.js.map → AdminLearner-SJNtSyJ_.js.map} +1 -1
  7. package/dist/assets/BaseUserDB-CV2ZPZOR.js +1 -0
  8. package/dist/assets/ClassroomCtrlPanel-BSAG3h8B.js +2 -0
  9. package/dist/assets/{ClassroomCtrlPanel-cj6bokz5.js.map → ClassroomCtrlPanel-BSAG3h8B.js.map} +1 -1
  10. package/dist/assets/{Classrooms-BIC1PGz0.js → Classrooms-DXNEbtsM.js} +3 -3
  11. package/dist/assets/{Classrooms-BIC1PGz0.js.map → Classrooms-DXNEbtsM.js.map} +1 -1
  12. package/dist/assets/CouchDBSyncStrategy-BjM7ROXC.js +1 -0
  13. package/dist/assets/CourseRouter-CsVa_92r.js +7 -0
  14. package/dist/assets/{CourseRouter-CMMxD9us.js.map → CourseRouter-CsVa_92r.js.map} +1 -1
  15. package/dist/assets/CourseSyncService-CPU_Ll1h.js +1 -0
  16. package/dist/assets/CourseWare-BTFRjgBR-DBp_fIwH.js +3 -0
  17. package/dist/assets/{CourseWare-BTFRjgBR-C3wi5YHa.js.map → CourseWare-BTFRjgBR-DBp_fIwH.js.map} +1 -1
  18. package/dist/assets/{Courses-Dw7mgMnI.js → Courses-CB6GGtdm.js} +3 -3
  19. package/dist/assets/{Courses-Dw7mgMnI.js.map → Courses-CB6GGtdm.js.map} +1 -1
  20. package/dist/assets/EloModeration-DUBgs-Vh.js +2 -0
  21. package/dist/assets/{EloModeration-COgCrvb8.js.map → EloModeration-DUBgs-Vh.js.map} +1 -1
  22. package/dist/assets/{JoinCode-Fu9Tks7r.js → JoinCode-BBvYapCA.js} +2 -2
  23. package/dist/assets/{JoinCode-Fu9Tks7r.js.map → JoinCode-BBvYapCA.js.map} +1 -1
  24. package/dist/assets/MarkdownRenderer-WG9YrHpe.js +1 -0
  25. package/dist/assets/MarkdownRenderer-borh39Lq.js +53 -0
  26. package/dist/assets/MarkdownRenderer-borh39Lq.js.map +1 -0
  27. package/dist/assets/NewCourseDialog-DBgFVnt3.js +2 -0
  28. package/dist/assets/{NewCourseDialog-C11dSwWM.js.map → NewCourseDialog-DBgFVnt3.js.map} +1 -1
  29. package/dist/assets/PipelineDebugger-BHaqzqZw.js +177 -0
  30. package/dist/assets/PipelineDebugger-BHaqzqZw.js.map +1 -0
  31. package/dist/assets/PouchDataLayerProvider-DxsnSIKd.js +2 -0
  32. package/dist/assets/PouchDataLayerProvider-DxsnSIKd.js.map +1 -0
  33. package/dist/assets/{ReleaseNotes-CeTkuF5d.js → ReleaseNotes-Dg6mLL1C.js} +2 -2
  34. package/dist/assets/{ReleaseNotes-CeTkuF5d.js.map → ReleaseNotes-Dg6mLL1C.js.map} +1 -1
  35. package/dist/assets/RequestPasswordReset-CcFMTnTc.js +2 -0
  36. package/dist/assets/{RequestPasswordReset-vTzfGItp.js.map → RequestPasswordReset-CcFMTnTc.js.map} +1 -1
  37. package/dist/assets/ResetPassword-Dw_cBJU2.js +2 -0
  38. package/dist/assets/{ResetPassword-CmGaVYsI.js.map → ResetPassword-Dw_cBJU2.js.map} +1 -1
  39. package/dist/assets/StaticDataLayerProvider-CtgU3VBh.js +2 -0
  40. package/dist/assets/StaticDataLayerProvider-CtgU3VBh.js.map +1 -0
  41. package/dist/assets/Study-DDsGQCTJ.js +2 -0
  42. package/dist/assets/{Study-CkJvraIv.js.map → Study-DDsGQCTJ.js.map} +1 -1
  43. package/dist/assets/TagInformation-DBLoXA2a.js +2 -0
  44. package/dist/assets/{TagInformation-xZcQ1C1t.js.map → TagInformation-DBLoXA2a.js.map} +1 -1
  45. package/dist/assets/User-DfXUXjFb.js +2 -0
  46. package/dist/assets/User-DfXUXjFb.js.map +1 -0
  47. package/dist/assets/UserDBDebugger-DPqlc4O_.js +23 -0
  48. package/dist/assets/UserDBDebugger-DPqlc4O_.js.map +1 -0
  49. package/dist/assets/UserDBDebugger-xmycWjck.js +1 -0
  50. package/dist/assets/UserStats-C04YVYv7.js +2 -0
  51. package/dist/assets/{UserStats-CioNBbmL.js.map → UserStats-C04YVYv7.js.map} +1 -1
  52. package/dist/assets/VerifyEmail-Y05BSR57.js +2 -0
  53. package/dist/assets/{VerifyEmail-Bh-T9191.js.map → VerifyEmail-Y05BSR57.js.map} +1 -1
  54. package/dist/assets/admin-DcFjvYJw.js +21 -0
  55. package/dist/assets/admin-DcFjvYJw.js.map +1 -0
  56. package/dist/assets/chess-E2uOAyQS-BZi0vihz.js +7 -0
  57. package/dist/assets/{chess-E2uOAyQS-C8213VIQ.js.map → chess-E2uOAyQS-BZi0vihz.js.map} +1 -1
  58. package/dist/assets/chess-Lfm7Fsvs-DgN08Qx9.js +1 -0
  59. package/dist/assets/contentSource-DwznMSMs.js +34 -0
  60. package/dist/assets/contentSource-DwznMSMs.js.map +1 -0
  61. package/dist/assets/defineProperty-y9rbOPYz.js +1 -0
  62. package/dist/assets/dist-BcwaOf54.js +1 -0
  63. package/dist/assets/dist-BsRvt0gH.js +38 -0
  64. package/dist/assets/dist-BsRvt0gH.js.map +1 -0
  65. package/dist/assets/dist-CAHkbl3M.js +18 -0
  66. package/dist/assets/dist-CAHkbl3M.js.map +1 -0
  67. package/dist/assets/dist-CgW7D_Gh.js +1 -0
  68. package/dist/assets/dist-Dnehy0sn.js +1 -0
  69. package/dist/assets/dist-Dp6eBE2S.js +64 -0
  70. package/dist/assets/dist-Dp6eBE2S.js.map +1 -0
  71. package/dist/assets/edit-ui.es-BWqvElsJ.js +1 -0
  72. package/dist/assets/edit-ui.es-UaQFL_My.js +41 -0
  73. package/dist/assets/edit-ui.es-UaQFL_My.js.map +1 -0
  74. package/dist/assets/elo-B5qCwvSC.js +2 -0
  75. package/dist/assets/elo-B5qCwvSC.js.map +1 -0
  76. package/dist/assets/elo-COgu6Hu5.js +2 -0
  77. package/dist/assets/elo-COgu6Hu5.js.map +1 -0
  78. package/dist/assets/elo-Cwa8a3Yo.js +1 -0
  79. package/dist/assets/eloDistance-BV7vfiK5.js +2 -0
  80. package/dist/assets/eloDistance-BV7vfiK5.js.map +1 -0
  81. package/dist/assets/eloDistance-MReQeAuj.js +1 -0
  82. package/dist/assets/french-Dk7YG8Td-CD7Hms2j.js +2 -0
  83. package/dist/assets/{french-Dk7YG8Td-D9eV2DXL.js.map → french-Dk7YG8Td-CD7Hms2j.js.map} +1 -1
  84. package/dist/assets/french-evUMlbbq-nGCjilG6.js +1 -0
  85. package/dist/assets/hierarchyDefinition-DLC5DjaA.js +2 -0
  86. package/dist/assets/hierarchyDefinition-DLC5DjaA.js.map +1 -0
  87. package/dist/assets/{index-NFrxkZjT.css → index-B7mmpKZd.css} +1 -1
  88. package/dist/assets/index-CK-rfSIx.js +4 -0
  89. package/dist/assets/{index-CDxzcoT1.js.map → index-CK-rfSIx.js.map} +1 -1
  90. package/dist/assets/interferenceMitigator-D78KgOxz.js +2 -0
  91. package/dist/assets/interferenceMitigator-D78KgOxz.js.map +1 -0
  92. package/dist/assets/logshim-YQI0WloD.js +2 -0
  93. package/dist/assets/logshim-YQI0WloD.js.map +1 -0
  94. package/dist/assets/math-DR3fXDcX-C9KfHLHP.js +1 -0
  95. package/dist/assets/math-D_8HiEQR-E4QDLrWp.js +34 -0
  96. package/dist/assets/{math-D_8HiEQR-DdtcYQLB.js.map → math-D_8HiEQR-E4QDLrWp.js.map} +1 -1
  97. package/dist/assets/moment-DbT30ZpG.js +5 -0
  98. package/dist/assets/moment-DbT30ZpG.js.map +1 -0
  99. package/dist/assets/piano-BN5Btq91-CnKhyLGE.js +1 -0
  100. package/dist/assets/piano-DF1g6yaX-Ck3BH5EK.js +2 -0
  101. package/dist/assets/{piano-DF1g6yaX-B7f_kt1X.js.map → piano-DF1g6yaX-Ck3BH5EK.js.map} +1 -1
  102. package/dist/assets/pitch-CgGJFkZ1-Dd0LzmEe.js +2 -0
  103. package/dist/assets/{pitch-CgGJFkZ1-CuezrVTg.js.map → pitch-CgGJFkZ1-Dd0LzmEe.js.map} +1 -1
  104. package/dist/assets/pitch-Dn0iNqiS-BxAdpDDb.js +1 -0
  105. package/dist/assets/prescribed-BWO17Gan.js +2 -0
  106. package/dist/assets/prescribed-BWO17Gan.js.map +1 -0
  107. package/dist/assets/relativePriority-DwPMECAp.js +2 -0
  108. package/dist/assets/relativePriority-DwPMECAp.js.map +1 -0
  109. package/dist/assets/server-CqR7xtQy.js +2 -0
  110. package/dist/assets/server-CqR7xtQy.js.map +1 -0
  111. package/dist/assets/{sightsing-BFQ7HRig-CLh3Xcy7.js → sightsing-BFQ7HRig-DV69ELZf.js} +23 -23
  112. package/dist/assets/{sightsing-BFQ7HRig-CLh3Xcy7.js.map → sightsing-BFQ7HRig-DV69ELZf.js.map} +1 -1
  113. package/dist/assets/sightsing-CJX3k0Fd-CG94OiDr.js +1 -0
  114. package/dist/assets/srs-DGscV6W4.js +1 -0
  115. package/dist/assets/srs-DOsG9Y-i.js +2 -0
  116. package/dist/assets/srs-DOsG9Y-i.js.map +1 -0
  117. package/dist/assets/tagRoles-jR-PJAgj.js +2 -0
  118. package/dist/assets/tagRoles-jR-PJAgj.js.map +1 -0
  119. package/dist/assets/typing-BevtfWlp-CvStu5BY.js +2 -0
  120. package/dist/assets/{typing-BevtfWlp-B__x_Ia1.js.map → typing-BevtfWlp-CvStu5BY.js.map} +1 -1
  121. package/dist/assets/typing-k-ojjO7G-AF8vU_q7.js +1 -0
  122. package/dist/assets/userDBKeys-DYLGKnVC.js +4 -0
  123. package/dist/assets/userDBKeys-DYLGKnVC.js.map +1 -0
  124. package/dist/assets/userTagPreference-cZCPqadC.js +2 -0
  125. package/dist/assets/userTagPreference-cZCPqadC.js.map +1 -0
  126. package/dist/assets/validators-lpYAHmRR.js +2 -0
  127. package/dist/assets/validators-lpYAHmRR.js.map +1 -0
  128. package/dist/assets/word-work-BOnRlZgd-CCGZdwyf.js +2 -0
  129. package/dist/assets/{word-work-BOnRlZgd-CxcTzMPz.js.map → word-work-BOnRlZgd-CCGZdwyf.js.map} +1 -1
  130. package/dist/assets/word-work-Dd6tIKrt-BNTSCq5F.js +1 -0
  131. package/dist/assets/{workbox-window.prod.es5-r2bRTooK.js → workbox-window.prod.es5-YsLcd14J.js} +1 -1
  132. package/dist/assets/{workbox-window.prod.es5-r2bRTooK.js.map → workbox-window.prod.es5-YsLcd14J.js.map} +1 -1
  133. package/dist/index.html +17 -7
  134. package/dist/sw.js +1 -1
  135. package/dist/sw.js.map +1 -1
  136. package/package.json +7 -7
  137. package/dist/assets/AdminDashboard-CO2rxkF5.js +0 -2
  138. package/dist/assets/AdminLearner-CZO2Hlk1.js +0 -2
  139. package/dist/assets/ClassroomCtrlPanel-cj6bokz5.js +0 -2
  140. package/dist/assets/CourseRouter-CMMxD9us.js +0 -7
  141. package/dist/assets/CourseWare-BTFRjgBR-C3wi5YHa.js +0 -3
  142. package/dist/assets/EloModeration-COgCrvb8.js +0 -2
  143. package/dist/assets/MarkdownRenderer-U_iPiA2x-DDruDu7E.js +0 -53
  144. package/dist/assets/MarkdownRenderer-U_iPiA2x-DDruDu7E.js.map +0 -1
  145. package/dist/assets/MarkdownRenderer-U_iPiA2x-VCa5mXh1.js +0 -1
  146. package/dist/assets/NewCourseDialog-C11dSwWM.js +0 -2
  147. package/dist/assets/RequestPasswordReset-vTzfGItp.js +0 -2
  148. package/dist/assets/ResetPassword-CmGaVYsI.js +0 -2
  149. package/dist/assets/Study-CkJvraIv.js +0 -2
  150. package/dist/assets/TagInformation-xZcQ1C1t.js +0 -2
  151. package/dist/assets/User-MzKFSneO.js +0 -3
  152. package/dist/assets/User-MzKFSneO.js.map +0 -1
  153. package/dist/assets/UserStats-CioNBbmL.js +0 -2
  154. package/dist/assets/VerifyEmail-Bh-T9191.js +0 -2
  155. package/dist/assets/admin-Dt07rW2C.js +0 -21
  156. package/dist/assets/admin-Dt07rW2C.js.map +0 -1
  157. package/dist/assets/chess-E2uOAyQS-C8213VIQ.js +0 -7
  158. package/dist/assets/chess-Lfm7Fsvs-6ElY3d5h.js +0 -1
  159. package/dist/assets/common-ui.es-B9r6QiWN.js +0 -38
  160. package/dist/assets/common-ui.es-B9r6QiWN.js.map +0 -1
  161. package/dist/assets/common-ui.es-j6sezLNk.js +0 -1
  162. package/dist/assets/dist-BeppzTWu.js +0 -380
  163. package/dist/assets/dist-BeppzTWu.js.map +0 -1
  164. package/dist/assets/dist-C1hpwy00.js +0 -1
  165. package/dist/assets/dist-CKO_fXB-.js +0 -18
  166. package/dist/assets/dist-CKO_fXB-.js.map +0 -1
  167. package/dist/assets/dist-CkRURFlm.js +0 -1
  168. package/dist/assets/dist-V9Xbab2f.js +0 -12
  169. package/dist/assets/dist-V9Xbab2f.js.map +0 -1
  170. package/dist/assets/edit-ui.es-B00e6OcT.js +0 -36
  171. package/dist/assets/edit-ui.es-B00e6OcT.js.map +0 -1
  172. package/dist/assets/edit-ui.es-BGTYLTZO.js +0 -1
  173. package/dist/assets/french-Dk7YG8Td-D9eV2DXL.js +0 -2
  174. package/dist/assets/french-evUMlbbq-DOmp0PEx.js +0 -1
  175. package/dist/assets/index-CDxzcoT1.js +0 -4
  176. package/dist/assets/math-DR3fXDcX-Clr1rrj8.js +0 -1
  177. package/dist/assets/math-D_8HiEQR-DdtcYQLB.js +0 -34
  178. package/dist/assets/piano-BN5Btq91-BO9b38qV.js +0 -1
  179. package/dist/assets/piano-DF1g6yaX-B7f_kt1X.js +0 -2
  180. package/dist/assets/pitch-CgGJFkZ1-CuezrVTg.js +0 -2
  181. package/dist/assets/pitch-Dn0iNqiS-L0LRhcjZ.js +0 -1
  182. package/dist/assets/server-BP-NvFg7.js +0 -2
  183. package/dist/assets/server-BP-NvFg7.js.map +0 -1
  184. package/dist/assets/sightsing-CJX3k0Fd-DiVzeNly.js +0 -1
  185. package/dist/assets/typing-BevtfWlp-B__x_Ia1.js +0 -2
  186. package/dist/assets/typing-k-ojjO7G-Dn4uH4pS.js +0 -1
  187. package/dist/assets/word-work-BOnRlZgd-CxcTzMPz.js +0 -2
  188. package/dist/assets/word-work-Dd6tIKrt-BOmhWlr6.js +0 -1
  189. /package/dist/assets/{common-ui-BY2Ut5jf.css → dist-BY2Ut5jf.css} +0 -0
@@ -0,0 +1,18 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/chess-Lfm7Fsvs-DgN08Qx9.js","assets/PipelineDebugger-BHaqzqZw.js","assets/defineProperty-y9rbOPYz.js","assets/chunk-D6hFPZc3.js","assets/MarkdownRenderer-borh39Lq.js","assets/vue.runtime.esm-bundler--Fxmd6l9.js","assets/moment-DbT30ZpG.js","assets/logshim-YQI0WloD.js","assets/contentSource-DwznMSMs.js","assets/elo-B5qCwvSC.js","assets/tagRoles-jR-PJAgj.js","assets/eloDistance-BV7vfiK5.js","assets/elo-COgu6Hu5.js","assets/srs-DOsG9Y-i.js","assets/userDBKeys-DYLGKnVC.js","assets/dist-BsRvt0gH.js","assets/vue-router-HoUBO3s7.js","assets/dist-Dp6eBE2S.js","assets/dist-BY2Ut5jf.css","assets/CourseWare-BTFRjgBR-DBp_fIwH.js","assets/CourseWare-BTFRjgBR-D750E7i0.css","assets/chess-E2uOAyQS-BZi0vihz.js","assets/chess-E2uOAyQS-DB7z_kWx.css","assets/french-evUMlbbq-nGCjilG6.js","assets/french-Dk7YG8Td-CD7Hms2j.js","assets/validators-lpYAHmRR.js","assets/math-DR3fXDcX-C9KfHLHP.js","assets/math-D_8HiEQR-E4QDLrWp.js","assets/math-D_8HiEQR-CZyvKZtp.css","assets/piano-BN5Btq91-CnKhyLGE.js","assets/piano-DF1g6yaX-Ck3BH5EK.js","assets/piano-DF1g6yaX-BLvDAgl1.css","assets/pitch-Dn0iNqiS-BxAdpDDb.js","assets/pitch-CgGJFkZ1-Dd0LzmEe.js","assets/sightsing-CJX3k0Fd-CG94OiDr.js","assets/sightsing-BFQ7HRig-DV69ELZf.js","assets/sightsing-BFQ7HRig-DkUGf5Yf.css","assets/typing-k-ojjO7G-AF8vU_q7.js","assets/typing-BevtfWlp-CvStu5BY.js","assets/typing-BevtfWlp-B7ZMUAQJ.css","assets/word-work-Dd6tIKrt-BNTSCq5F.js","assets/word-work-BOnRlZgd-CCGZdwyf.js"])))=>i.map(i=>d[i]);
2
+ import"./chunk-D6hFPZc3.js";import{$ as e,C as t,H as n,Ht as r,K as i,S as a,T as o,W as s,Z as c,_ as l,b as u,f as d,g as f,ot as p,ut as m,v as h,y as g,z as _}from"./vue.runtime.esm-bundler--Fxmd6l9.js";import{z as v}from"./dist-BsRvt0gH.js";import{K as y,W as b}from"./contentSource-DwznMSMs.js";import{t as x}from"./defineProperty-y9rbOPYz.js";import{n as S,r as C,t as w,u as T}from"./CourseWare-BTFRjgBR-DBp_fIwH.js";import{j as E}from"./PipelineDebugger-BHaqzqZw.js";import{d as D}from"./userDBKeys-DYLGKnVC.js";import{r as O}from"./piano-DF1g6yaX-Ck3BH5EK.js";var k=new S(`default`,[C]),A=o({name:`PianoRangeVisualizer`,props:{lowestNote:{type:Number,required:!0},highestNote:{type:Number,required:!0},maxWidth:{type:Number,default:1e3}},setup(e){let t=m(null),n=m(800),r=f(()=>{let e=0;for(let t=21;t<=108;t++)isWhiteKey(t)&&e++;return e}),i=f(()=>Math.min(22,n.value/Math.max(25,r.value))),a=f(()=>i.value*.6),o=f(()=>Math.min(e.maxWidth,i.value*r.value+10)),isWhiteKey=e=>{let t=e%12;return[0,2,4,5,7,9,11].includes(t)},getKeyPosition=e=>{let t=0;for(let n=21;n<e;n++)isWhiteKey(n)&&t++;return isWhiteKey(e)?t*i.value:t*i.value-a.value/2},getNoteLabel=e=>{let t=[`C`,`C#`,`D`,`D#`,`E`,`F`,`F#`,`G`,`G#`,`A`,`A#`,`B`],n=e%12,r=Math.floor(e/12)-1;return`${t[n]}${r}`};return _(()=>{t.value&&(n.value=t.value.clientWidth,new ResizeObserver(e=>{for(let t of e)n.value=t.contentRect.width}).observe(t.value))}),{pianoWrapper:t,keyHeight:100,blackKeyHeight:60,whiteKeyWidth:i,blackKeyWidth:a,svgWidth:o,isWhiteKey,getKeyPosition,getNoteLabel}}}),j={class:`piano-range-container`},M={class:`piano-wrapper`,ref:`pianoWrapper`},N=[`width`,`height`],P={class:`background-keys`,opacity:`0.15`},F=[`x`,`width`,`height`],I=[`x`,`width`,`height`],L={class:`selected-range`},R=[`x`,`width`,`height`],z=[`x`,`width`,`height`],B={class:`range-markers`},V=[`x`,`height`],H=[`x`,`height`],U=[`x`,`y`],W=[`x`,`y`];function _sfc_render$1(e,t,i,a,o,c){return n(),u(`div`,j,[l(`div`,M,[(n(),u(`svg`,{width:e.svgWidth,height:e.keyHeight+20,class:`piano-svg`},[l(`g`,P,[(n(),u(d,null,s(88,t=>(n(),u(d,{key:`bg-${t}`},[e.isWhiteKey(t+20)?(n(),u(`rect`,{key:0,x:e.getKeyPosition(t+20),y:`0`,width:e.whiteKeyWidth,height:e.keyHeight,class:`white-key`,stroke:`#999`,"stroke-width":`1`},null,8,F)):g(``,!0)],64))),64)),(n(),u(d,null,s(88,t=>(n(),u(d,{key:`bg-black-${t}`},[e.isWhiteKey(t+20)?g(``,!0):(n(),u(`rect`,{key:0,x:e.getKeyPosition(t+20),y:`0`,width:e.blackKeyWidth,height:e.blackKeyHeight,class:`black-key`},null,8,I))],64))),64))]),l(`g`,L,[(n(),u(d,null,s(128,t=>(n(),u(d,{key:`white-${t}`},[e.isWhiteKey(t)&&t>=e.lowestNote&&t<=e.highestNote?(n(),u(`rect`,{key:0,x:e.getKeyPosition(t),y:`0`,width:e.whiteKeyWidth,height:e.keyHeight,class:`white-key active`,stroke:`#666`,"stroke-width":`1`},null,8,R)):g(``,!0)],64))),64)),(n(),u(d,null,s(128,t=>(n(),u(d,{key:`black-${t}`},[!e.isWhiteKey(t)&&t>=e.lowestNote&&t<=e.highestNote?(n(),u(`rect`,{key:0,x:e.getKeyPosition(t),y:`0`,width:e.blackKeyWidth,height:e.blackKeyHeight,class:`black-key active`},null,8,z)):g(``,!0)],64))),64))]),l(`g`,B,[l(`rect`,{x:e.getKeyPosition(e.lowestNote)-2,y:`0`,width:4,height:e.keyHeight+5,class:`range-marker start`},null,8,V),l(`rect`,{x:e.getKeyPosition(e.highestNote)+e.whiteKeyWidth-2,y:`0`,width:4,height:e.keyHeight+5,class:`range-marker end`},null,8,H)]),l(`text`,{x:e.getKeyPosition(e.lowestNote)+3,y:e.keyHeight+12,class:`note-label`},r(e.getNoteLabel(e.lowestNote)),9,U),l(`text`,{x:e.getKeyPosition(e.highestNote)+e.whiteKeyWidth-3,y:e.keyHeight+12,"text-anchor":`end`,class:`note-label`},r(e.getNoteLabel(e.highestNote)),9,W)],8,N))],512)])}T(_sfc_render$1,`_sfc_render`);var G=o({name:`MidiConfig`,components:{PianoRangeVisualizer:w(A,[[`render`,_sfc_render$1],[`__scopeId`,`data-v-4b232a8b`]])},props:{_id:{type:String,required:!0},user:{type:Object,required:!0}},setup(e){let t=m(),n=m(!0),r=m([]),i=m([]),a=m(``),o=m(``),s=m(!1),l=m(``),u=m(``),d=m(!1),f=m(`full-88`),p=m(21),h=m(108),g=m(``),b=m(0),x=m(0),S=m([]),initNoteOptions=()=>{let e=[`C`,`C#`,`D`,`D#`,`E`,`F`,`F#`,`G`,`G#`,`A`,`A#`,`B`],t=[];for(let n=0;n<=127;n++){let r=Math.floor(n/12)-1,i=e[n%12];t.push({title:`${i}${r} (${n})`,value:n})}S.value=t},C=m([{title:`Full 88-key Piano (A0-C8)`,value:`full-88`},{title:`76-key Keyboard (E1-G7)`,value:`76-key`},{title:`61-key Keyboard (C2-C7)`,value:`61-key`},{title:`49-key Keyboard (C3-C7)`,value:`49-key`},{title:`37-key Keyboard (C3-C6)`,value:`37-key`},{title:`25-key Keyboard (C4-C6)`,value:`25-key`},{title:`Custom Range`,value:`custom`}]),checkConfigChanged=()=>{d.value=a.value!==l.value||o.value!==u.value||f.value!==g.value||f.value===`custom`&&(p.value!==b.value||h.value!==x.value)},updateCustomRangeFromPreset=()=>{switch(f.value){case`full-88`:p.value=21,h.value=108;break;case`76-key`:p.value=28,h.value=103;break;case`61-key`:p.value=36,h.value=96;break;case`49-key`:p.value=48,h.value=96;break;case`37-key`:p.value=48,h.value=84;break;case`25-key`:p.value=60,h.value=84;break}checkConfigChanged()},updateRangeAndCheckChanges=()=>{p.value>=h.value&&(h.value=p.value+12),checkConfigChanged()},playSound=()=>{t.value?.play([{note:{number:64,name:`E`,octave:4},type:`noteon`,velocity:.4251968503937008,timestamp:0},{note:{number:64,name:`E`,octave:4},velocity:.3779527559055118,type:`noteoff`,timestamp:511.90500000002794},{note:{number:60,name:`C`,octave:4},type:`noteon`,velocity:.5275590551181102,timestamp:535.8800000001211},{note:{number:60,name:`C`,octave:4},velocity:.33858267716535434,type:`noteoff`,timestamp:674.9899999999907},{note:{number:60,name:`C`,octave:4},type:`noteon`,velocity:.5590551181102362,timestamp:1070.8800000000047},{note:{number:60,name:`C`,octave:4},velocity:.3464566929133858,type:`noteoff`,timestamp:1214.8999999999069},{note:{number:64,name:`E`,octave:4},type:`noteon`,velocity:.5118110236220472,timestamp:1424.9400000000605},{note:{number:64,name:`E`,octave:4},velocity:.2755905511811024,type:`noteoff`,timestamp:1576.9150000000373},{note:{number:62,name:`D`,octave:4},type:`noteon`,velocity:.3937007874015748,timestamp:1756.9149999999208},{note:{number:62,name:`D`,octave:4},velocity:.36220472440944884,type:`noteoff`,timestamp:1926.9899999998743},{note:{number:60,name:`C`,octave:4},type:`noteon`,velocity:.5196850393700787,timestamp:1970.9600000000792},{note:{number:60,name:`C`,octave:4},velocity:.36220472440944884,type:`noteoff`,timestamp:2126.009999999893},{note:{number:60,name:`C`,octave:4},type:`noteon`,velocity:.5984251968503937,timestamp:2502.0050000000047},{note:{number:60,name:`C`,octave:4},velocity:.3858267716535433,type:`noteoff`,timestamp:2853.920000000042},{note:{number:67,name:`G`,octave:4},type:`noteon`,velocity:.6850393700787402,timestamp:2875.8649999999907},{note:{number:67,name:`G`,octave:4},velocity:.6377952755905512,type:`noteoff`,timestamp:4497.004999999888}])},indicateHeardNotes=e=>{v({text:`I hear a ${e.note.name}!`,status:y.ok})};c(a,()=>{t.value?.selectInput(a.value),checkConfigChanged()}),c(o,()=>{t.value?.selectOutput(o.value),checkConfigChanged()});let retrieveSettings=async()=>{let t=await(await e.user.getCourseInterface(e._id)).getCourseSettings();if(t?.midiinput){let e=t.midiinput.toString();r.value.some(t=>t.value===e)&&(a.value=e,l.value=e)}if(t?.midioutput){let e=t.midioutput.toString();i.value.some(t=>t.value===e)&&(o.value=e,u.value=e)}t?.keyboardRange&&(g.value=t.keyboardRange.toString(),f.value=g.value),t?.lowestNote&&(b.value=parseInt(t.lowestNote.toString()),p.value=b.value),t?.highestNote&&(x.value=parseInt(t.highestNote.toString()),h.value=x.value),t?.lowestNote&&t?.highestNote&&!t?.keyboardRange&&(f.value=`custom`),d.value=!1},saveSettings=async()=>{s.value=!0,(await D().getUserDB().getCourseInterface(e._id)).updateCourseSettings([{key:`midiinput`,value:a.value},{key:`midioutput`,value:o.value},{key:`keyboardRange`,value:f.value},{key:`lowestNote`,value:p.value},{key:`highestNote`,value:h.value}]),l.value=a.value,u.value=o.value,g.value=f.value,b.value=p.value,x.value=h.value,d.value=!1,s.value=!1,v({text:`Settings updated.`,status:y.ok})};return _(async()=>{initNoteOptions();try{t.value=await O.instance(),n.value=t.value.state===`ready`||t.value.state===`nodevice`}catch(e){console.log(`Error on midi Init: ${e}`),n.value=!1}n.value&&(t.value?.addNoteonListenter(indicateHeardNotes),t.value?(r.value=t.value.inputs.filter(e=>e.state===`connected`).map(e=>({title:`${e.manufacturer}: ${e.name}`,value:e.id})),i.value=t.value?.outputs.filter(e=>e.state===`connected`).map(e=>({title:`${e.manufacturer}: ${e.name}`,value:e.id}))):(r.value=[{title:`No inputs available`,value:``}],i.value=[{title:`No outputs available`,value:``}]),await retrieveSettings(),!a.value&&r.value.length>0&&(a.value=r.value[0].value),!o.value&&i.value.length>0&&(o.value=i.value[0].value))}),{midiSupported:n,inputs:r,outputs:i,selectedInput:a,selectedOutput:o,updatePending:s,playSound,saveSettings,configChanged:d,lowestNote:p,highestNote:h,keyboardRangeOptions:C,selectedKeyboardRange:f,noteOptions:S,updateCustomRangeFromPreset,updateRangeAndCheckChanges}}}),K={key:0,class:`custom-range-inputs d-flex gap-4`},q={class:`d-flex justify-space-between mt-3`},J={key:1};function _sfc_render(r,o,s,c,d,f){let p=i(`v-toolbar-title`),m=i(`v-toolbar`),_=i(`v-select`),v=i(`v-divider`),y=i(`piano-range-visualizer`),b=i(`v-btn`),x=i(`v-form`),S=i(`v-card-text`),C=i(`v-card`);return n(),h(C,null,{default:e(()=>[t(m,{dense:``},{default:e(()=>[t(p,null,{default:e(()=>o[5]||(o[5]=[a(`Configure Midi Device`)])),_:1})]),_:1}),t(S,null,{default:e(()=>[r.midiSupported?(n(),h(x,{key:0,onsubmit:`return false;`},{default:e(()=>[t(_,{modelValue:r.selectedInput,"onUpdate:modelValue":o[0]||(o[0]=e=>r.selectedInput=e),items:r.inputs,label:`Select Input`,hint:`Play some notes on your input device to test the connection`},null,8,[`modelValue`,`items`]),t(_,{modelValue:r.selectedOutput,"onUpdate:modelValue":o[1]||(o[1]=e=>r.selectedOutput=e),items:r.outputs,label:`Select Output`},null,8,[`modelValue`,`items`]),t(v,{class:`my-4`}),o[8]||(o[8]=l(`h3`,{class:`text-subtitle-1 mb-2`},`Keyboard Range`,-1)),t(_,{modelValue:r.selectedKeyboardRange,"onUpdate:modelValue":[o[2]||(o[2]=e=>r.selectedKeyboardRange=e),r.updateCustomRangeFromPreset],items:r.keyboardRangeOptions,label:`Select Keyboard Range`},null,8,[`modelValue`,`items`,`onUpdate:modelValue`]),r.selectedKeyboardRange===`custom`?(n(),u(`div`,K,[t(_,{modelValue:r.lowestNote,"onUpdate:modelValue":[o[3]||(o[3]=e=>r.lowestNote=e),r.updateRangeAndCheckChanges],items:r.noteOptions,label:`Lowest Note`},null,8,[`modelValue`,`items`,`onUpdate:modelValue`]),t(_,{modelValue:r.highestNote,"onUpdate:modelValue":[o[4]||(o[4]=e=>r.highestNote=e),r.updateRangeAndCheckChanges],items:r.noteOptions,label:`Highest Note`},null,8,[`modelValue`,`items`,`onUpdate:modelValue`])])):g(``,!0),t(y,{"lowest-note":r.lowestNote,"highest-note":r.highestNote},null,8,[`lowest-note`,`highest-note`]),l(`div`,q,[t(b,{color:`primary`,onClick:r.playSound},{default:e(()=>o[6]||(o[6]=[a(`Test midi output`)])),_:1},8,[`onClick`]),t(b,{loading:r.updatePending,disabled:!r.configChanged&&!r.updatePending,color:`info`,class:`save-button`,onClick:r.saveSettings},{default:e(()=>o[7]||(o[7]=[a(` Save these settings `)])),_:1},8,[`loading`,`disabled`,`onClick`])])]),_:1})):(n(),u(`div`,J,o[9]||(o[9]=[l(`p`,null,`This quilt requires a midi input device, which is not supported by this browser.`,-1),l(`div`,null,[l(`p`,null,`Try one of the following browsers:`),l(`ul`,null,[l(`li`,null,[l(`a`,{href:`https://www.google.com/chrome/`},`Google Chrome`)]),l(`li`,null,[l(`a`,{href:`https://www.microsoft.com/edge`},`Microsoft Edge`)]),l(`li`,null,[l(`a`,{href:`https://brave.com/`},`Brave`)])])],-1)])))]),_:1})]),_:1})}var Y=w(G,[[`render`,_sfc_render],[`__scopeId`,`data-v-6ee9020f`]]);async function loadSubcourse(e){let t;switch(e){case`chess`:t=await E(()=>import(`./chess-Lfm7Fsvs-DgN08Qx9.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22]));break;case`french`:t=await E(()=>import(`./french-evUMlbbq-nGCjilG6.js`),__vite__mapDeps([23,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,24,25]));break;case`math`:t=await E(()=>import(`./math-DR3fXDcX-C9KfHLHP.js`),__vite__mapDeps([26,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,27,28]));break;case`piano`:t=await E(()=>import(`./piano-BN5Btq91-CnKhyLGE.js`),__vite__mapDeps([29,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,30,31]));break;case`pitch`:t=await E(()=>import(`./pitch-Dn0iNqiS-BxAdpDDb.js`),__vite__mapDeps([32,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,33]));break;case`sightSing`:t=await E(()=>import(`./sightsing-CJX3k0Fd-CG94OiDr.js`),__vite__mapDeps([34,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,35,36]));break;case`typing`:t=await E(()=>import(`./typing-k-ojjO7G-AF8vU_q7.js`),__vite__mapDeps([37,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,38,39]));break;case`wordWork`:t=await E(()=>import(`./word-work-Dd6tIKrt-BNTSCq5F.js`),__vite__mapDeps([40,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,41,25]));break}let n=t.default;return X.courses.find(e=>e.name===n.name)||X.courses.push(n),n}async function loadAllSubcourses(){await Promise.all([`chess`,`french`,`math`,`piano`,`pitch`,`sightSing`,`typing`,`wordWork`].map(e=>loadSubcourse(e)))}var AllCourseWare=class{get courses(){return this.courseWareList}constructor(e){x(this,`courseWareList`,void 0),x(this,`cachedRawViews`,null),this.courseWareList=e}getCourseWare(e){return this.courseWareList.find(t=>t.name===e)}allViewsRaw(){if(!this.cachedRawViews){let e=this.allViews();this.cachedRawViews=Object.fromEntries(Object.entries(e).map(([e,t])=>[e,p(t)]))}return this.cachedRawViews}allViews(){let e={};return this.courseWareList.forEach(t=>{Object.assign(e,t.allViewsMap)}),e}getView(e){let t;t=typeof e==`string`?b.getViewDescriptor(e):e;let n=this.getCourseWare(t.course);if(n){let e=n.getQuestion(t.questionType);if(e){let r=e.views.find(e=>e.name===t.view);if(r)return r;throw console.error(`QuestionView ${t.view} not found in course ${t.course}
3
+
4
+ descriptor: ${JSON.stringify(t)}
5
+
6
+ course: ${n.name}
7
+ question: ${e.name}
8
+ views: ${e.views.map(e=>e.name).join(`, `)}
9
+ `),Error(`view ${t.view} does not exist.`)}else throw console.error(`Question ${t.questionType} not found in course ${t.course}
10
+
11
+ descriptor: ${JSON.stringify(t)}
12
+
13
+ course: ${n.name}
14
+ questions: ${n.questions.map(e=>e.name).join(`, `)}
15
+ `),Error(`question ${t.questionType} does not exist.`)}else throw console.error(`Course ${t.course} not found.
16
+
17
+ descriptor: ${JSON.stringify(t)}`),Error(`course ${t.course} does not exist.`)}toString(){let e=``;return this.courses.forEach(t=>{e+=`Course: ${t.name}\n`,t.questions.forEach(t=>{e+=` Question: ${t.name}\n`,t.views.forEach(t=>{e+=` View: ${t.name}\n`})})}),e}allDataShapesRaw(){let e=[];return this.courseWareList.forEach(t=>{t.questions.forEach(t=>{t.dataShapes.forEach(t=>{e.includes(t)||e.push(t)})})}),e}allDataShapes(){let e=[];return this.courseWareList.forEach(t=>{t.questions.forEach(n=>{n.dataShapes.forEach(r=>{e.findIndex(e=>e.course===t.name&&e.dataShape===r.name)===-1&&e.push({course:t.name,dataShape:r.name,displayable:n})})})}),e}getDataShape(e){let t;if(this.getCourseWare(e.course).questions.forEach(n=>{n.dataShapes.forEach(n=>{n.name===e.dataShape&&(t=n)})}),t)return t;throw Error(`DataShape ${b.getDataShapeString(e)} not found`)}},X=new AllCourseWare([]);export{loadAllSubcourses as a,Y as i,AllCourseWare as n,loadSubcourse as o,k as r,X as t};
18
+ //# sourceMappingURL=dist-CAHkbl3M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"mappings":"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","names":["a","r","D","j","b","k","A","C","w","y","M","S","P","e","i","n","V","F","H","z","p","N","x","I","E","T","O","B"],"ignoreList":[],"sources":["../../../courseware/dist/index.mjs"],"sourcesContent":["import { r as e, t } from \"./shapes-BQUVJdp5.js\";\nimport { i as n, n as r, r as i, t as a } from \"./CourseWare-BTFRjgBR.js\";\nimport { t as o } from \"./chess-E2uOAyQS.js\";\nimport { t as s } from \"./french-Dk7YG8Td.js\";\nimport { t as c } from \"./math-D_8HiEQR.js\";\nimport { a as l, i as u, n as d, o as f, r as p, t as m } from \"./piano-DF1g6yaX.js\";\nimport { t as h } from \"./pitch-CgGJFkZ1.js\";\nimport { t as g } from \"./sightsing-BFQ7HRig.js\";\nimport { t as _ } from \"./typing-BevtfWlp.js\";\nimport { t as v } from \"./word-work-BOnRlZgd.js\";\nimport { Fragment as y, computed as b, createBlock as x, createCommentVNode as S, createElementBlock as C, createElementVNode as w, createTextVNode as T, createVNode as E, defineComponent as D, markRaw as O, onMounted as k, openBlock as A, ref as j, renderList as M, resolveComponent as N, toDisplayString as P, watch as F, withCtx as I } from \"vue\";\nimport { Displayable as L, Question as R, alertUser as z, useQuestionView as ee, useViewable as te } from \"@vue-skuilder/common-ui\";\nimport { NameSpacer as B, Status as V } from \"@vue-skuilder/common\";\nimport { getDataLayer as H } from \"@vue-skuilder/db\";\nimport './assets/index.css';//#region src/default/index.ts\nvar U = new a(\"default\", [r]), W = D({\n\tname: \"PianoRangeVisualizer\",\n\tprops: {\n\t\tlowestNote: {\n\t\t\ttype: Number,\n\t\t\trequired: !0\n\t\t},\n\t\thighestNote: {\n\t\t\ttype: Number,\n\t\t\trequired: !0\n\t\t},\n\t\tmaxWidth: {\n\t\t\ttype: Number,\n\t\t\tdefault: 1e3\n\t\t}\n\t},\n\tsetup(e) {\n\t\tlet t = j(null), n = j(800), r = b(() => {\n\t\t\tlet e = 0;\n\t\t\tfor (let t = 21; t <= 108; t++) isWhiteKey(t) && e++;\n\t\t\treturn e;\n\t\t}), i = b(() => Math.min(22, n.value / Math.max(25, r.value))), a = b(() => i.value * .6), o = b(() => Math.min(e.maxWidth, i.value * r.value + 10)), isWhiteKey = (e) => {\n\t\t\tlet t = e % 12;\n\t\t\treturn [\n\t\t\t\t0,\n\t\t\t\t2,\n\t\t\t\t4,\n\t\t\t\t5,\n\t\t\t\t7,\n\t\t\t\t9,\n\t\t\t\t11\n\t\t\t].includes(t);\n\t\t}, getKeyPosition = (e) => {\n\t\t\tlet t = 0;\n\t\t\tfor (let n = 21; n < e; n++) isWhiteKey(n) && t++;\n\t\t\treturn isWhiteKey(e) ? t * i.value : t * i.value - a.value / 2;\n\t\t}, getNoteLabel = (e) => {\n\t\t\tlet t = [\n\t\t\t\t\"C\",\n\t\t\t\t\"C#\",\n\t\t\t\t\"D\",\n\t\t\t\t\"D#\",\n\t\t\t\t\"E\",\n\t\t\t\t\"F\",\n\t\t\t\t\"F#\",\n\t\t\t\t\"G\",\n\t\t\t\t\"G#\",\n\t\t\t\t\"A\",\n\t\t\t\t\"A#\",\n\t\t\t\t\"B\"\n\t\t\t], n = e % 12, r = Math.floor(e / 12) - 1;\n\t\t\treturn `${t[n]}${r}`;\n\t\t};\n\t\treturn k(() => {\n\t\t\tt.value && (n.value = t.value.clientWidth, new ResizeObserver((e) => {\n\t\t\t\tfor (let t of e) n.value = t.contentRect.width;\n\t\t\t}).observe(t.value));\n\t\t}), {\n\t\t\tpianoWrapper: t,\n\t\t\tkeyHeight: 100,\n\t\t\tblackKeyHeight: 60,\n\t\t\twhiteKeyWidth: i,\n\t\t\tblackKeyWidth: a,\n\t\t\tsvgWidth: o,\n\t\t\tisWhiteKey,\n\t\t\tgetKeyPosition,\n\t\t\tgetNoteLabel\n\t\t};\n\t}\n}), G = { class: \"piano-range-container\" }, K = {\n\tclass: \"piano-wrapper\",\n\tref: \"pianoWrapper\"\n}, q = [\"width\", \"height\"], J = {\n\tclass: \"background-keys\",\n\topacity: \"0.15\"\n}, Y = [\n\t\"x\",\n\t\"width\",\n\t\"height\"\n], X = [\n\t\"x\",\n\t\"width\",\n\t\"height\"\n], Z = { class: \"selected-range\" }, ne = [\n\t\"x\",\n\t\"width\",\n\t\"height\"\n], re = [\n\t\"x\",\n\t\"width\",\n\t\"height\"\n], ie = { class: \"range-markers\" }, ae = [\"x\", \"height\"], oe = [\"x\", \"height\"], se = [\"x\", \"y\"], ce = [\"x\", \"y\"];\nfunction _sfc_render$1(e, t, n, r, i, a) {\n\treturn A(), C(\"div\", G, [w(\"div\", K, [(A(), C(\"svg\", {\n\t\twidth: e.svgWidth,\n\t\theight: e.keyHeight + 20,\n\t\tclass: \"piano-svg\"\n\t}, [\n\t\tw(\"g\", J, [(A(), C(y, null, M(88, (t) => (A(), C(y, { key: `bg-${t}` }, [e.isWhiteKey(t + 20) ? (A(), C(\"rect\", {\n\t\t\tkey: 0,\n\t\t\tx: e.getKeyPosition(t + 20),\n\t\t\ty: \"0\",\n\t\t\twidth: e.whiteKeyWidth,\n\t\t\theight: e.keyHeight,\n\t\t\tclass: \"white-key\",\n\t\t\tstroke: \"#999\",\n\t\t\t\"stroke-width\": \"1\"\n\t\t}, null, 8, Y)) : S(\"\", !0)], 64))), 64)), (A(), C(y, null, M(88, (t) => (A(), C(y, { key: `bg-black-${t}` }, [e.isWhiteKey(t + 20) ? S(\"\", !0) : (A(), C(\"rect\", {\n\t\t\tkey: 0,\n\t\t\tx: e.getKeyPosition(t + 20),\n\t\t\ty: \"0\",\n\t\t\twidth: e.blackKeyWidth,\n\t\t\theight: e.blackKeyHeight,\n\t\t\tclass: \"black-key\"\n\t\t}, null, 8, X))], 64))), 64))]),\n\t\tw(\"g\", Z, [(A(), C(y, null, M(128, (t) => (A(), C(y, { key: `white-${t}` }, [e.isWhiteKey(t) && t >= e.lowestNote && t <= e.highestNote ? (A(), C(\"rect\", {\n\t\t\tkey: 0,\n\t\t\tx: e.getKeyPosition(t),\n\t\t\ty: \"0\",\n\t\t\twidth: e.whiteKeyWidth,\n\t\t\theight: e.keyHeight,\n\t\t\tclass: \"white-key active\",\n\t\t\tstroke: \"#666\",\n\t\t\t\"stroke-width\": \"1\"\n\t\t}, null, 8, ne)) : S(\"\", !0)], 64))), 64)), (A(), C(y, null, M(128, (t) => (A(), C(y, { key: `black-${t}` }, [!e.isWhiteKey(t) && t >= e.lowestNote && t <= e.highestNote ? (A(), C(\"rect\", {\n\t\t\tkey: 0,\n\t\t\tx: e.getKeyPosition(t),\n\t\t\ty: \"0\",\n\t\t\twidth: e.blackKeyWidth,\n\t\t\theight: e.blackKeyHeight,\n\t\t\tclass: \"black-key active\"\n\t\t}, null, 8, re)) : S(\"\", !0)], 64))), 64))]),\n\t\tw(\"g\", ie, [w(\"rect\", {\n\t\t\tx: e.getKeyPosition(e.lowestNote) - 2,\n\t\t\ty: \"0\",\n\t\t\twidth: 4,\n\t\t\theight: e.keyHeight + 5,\n\t\t\tclass: \"range-marker start\"\n\t\t}, null, 8, ae), w(\"rect\", {\n\t\t\tx: e.getKeyPosition(e.highestNote) + e.whiteKeyWidth - 2,\n\t\t\ty: \"0\",\n\t\t\twidth: 4,\n\t\t\theight: e.keyHeight + 5,\n\t\t\tclass: \"range-marker end\"\n\t\t}, null, 8, oe)]),\n\t\tw(\"text\", {\n\t\t\tx: e.getKeyPosition(e.lowestNote) + 3,\n\t\t\ty: e.keyHeight + 12,\n\t\t\tclass: \"note-label\"\n\t\t}, P(e.getNoteLabel(e.lowestNote)), 9, se),\n\t\tw(\"text\", {\n\t\t\tx: e.getKeyPosition(e.highestNote) + e.whiteKeyWidth - 3,\n\t\t\ty: e.keyHeight + 12,\n\t\t\t\"text-anchor\": \"end\",\n\t\t\tclass: \"note-label\"\n\t\t}, P(e.getNoteLabel(e.highestNote)), 9, ce)\n\t], 8, q))], 512)]);\n}\ne(_sfc_render$1, \"_sfc_render\");\n//#endregion\n//#region src/piano/utility/MidiConfig.vue?vue&type=script&lang.ts\nvar le = D({\n\tname: \"MidiConfig\",\n\tcomponents: { PianoRangeVisualizer: /* @__PURE__ */ i(W, [[\"render\", _sfc_render$1], [\"__scopeId\", \"data-v-4b232a8b\"]]) },\n\tprops: {\n\t\t_id: {\n\t\t\ttype: String,\n\t\t\trequired: !0\n\t\t},\n\t\tuser: {\n\t\t\ttype: Object,\n\t\t\trequired: !0\n\t\t}\n\t},\n\tsetup(e) {\n\t\tlet t = j(), n = j(!0), r = j([]), i = j([]), a = j(\"\"), o = j(\"\"), s = j(!1), c = j(\"\"), l = j(\"\"), u = j(!1), d = j(\"full-88\"), f = j(21), m = j(108), h = j(\"\"), g = j(0), _ = j(0), v = j([]), initNoteOptions = () => {\n\t\t\tlet e = [\n\t\t\t\t\"C\",\n\t\t\t\t\"C#\",\n\t\t\t\t\"D\",\n\t\t\t\t\"D#\",\n\t\t\t\t\"E\",\n\t\t\t\t\"F\",\n\t\t\t\t\"F#\",\n\t\t\t\t\"G\",\n\t\t\t\t\"G#\",\n\t\t\t\t\"A\",\n\t\t\t\t\"A#\",\n\t\t\t\t\"B\"\n\t\t\t], t = [];\n\t\t\tfor (let n = 0; n <= 127; n++) {\n\t\t\t\tlet r = Math.floor(n / 12) - 1, i = e[n % 12];\n\t\t\t\tt.push({\n\t\t\t\t\ttitle: `${i}${r} (${n})`,\n\t\t\t\t\tvalue: n\n\t\t\t\t});\n\t\t\t}\n\t\t\tv.value = t;\n\t\t}, y = j([\n\t\t\t{\n\t\t\t\ttitle: \"Full 88-key Piano (A0-C8)\",\n\t\t\t\tvalue: \"full-88\"\n\t\t\t},\n\t\t\t{\n\t\t\t\ttitle: \"76-key Keyboard (E1-G7)\",\n\t\t\t\tvalue: \"76-key\"\n\t\t\t},\n\t\t\t{\n\t\t\t\ttitle: \"61-key Keyboard (C2-C7)\",\n\t\t\t\tvalue: \"61-key\"\n\t\t\t},\n\t\t\t{\n\t\t\t\ttitle: \"49-key Keyboard (C3-C7)\",\n\t\t\t\tvalue: \"49-key\"\n\t\t\t},\n\t\t\t{\n\t\t\t\ttitle: \"37-key Keyboard (C3-C6)\",\n\t\t\t\tvalue: \"37-key\"\n\t\t\t},\n\t\t\t{\n\t\t\t\ttitle: \"25-key Keyboard (C4-C6)\",\n\t\t\t\tvalue: \"25-key\"\n\t\t\t},\n\t\t\t{\n\t\t\t\ttitle: \"Custom Range\",\n\t\t\t\tvalue: \"custom\"\n\t\t\t}\n\t\t]), checkConfigChanged = () => {\n\t\t\tu.value = a.value !== c.value || o.value !== l.value || d.value !== h.value || d.value === \"custom\" && (f.value !== g.value || m.value !== _.value);\n\t\t}, updateCustomRangeFromPreset = () => {\n\t\t\tswitch (d.value) {\n\t\t\t\tcase \"full-88\":\n\t\t\t\t\tf.value = 21, m.value = 108;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"76-key\":\n\t\t\t\t\tf.value = 28, m.value = 103;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"61-key\":\n\t\t\t\t\tf.value = 36, m.value = 96;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"49-key\":\n\t\t\t\t\tf.value = 48, m.value = 96;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"37-key\":\n\t\t\t\t\tf.value = 48, m.value = 84;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"25-key\":\n\t\t\t\t\tf.value = 60, m.value = 84;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcheckConfigChanged();\n\t\t}, updateRangeAndCheckChanges = () => {\n\t\t\tf.value >= m.value && (m.value = f.value + 12), checkConfigChanged();\n\t\t}, playSound = () => {\n\t\t\tt.value?.play([\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 64,\n\t\t\t\t\t\tname: \"E\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\ttype: \"noteon\",\n\t\t\t\t\tvelocity: .4251968503937008,\n\t\t\t\t\ttimestamp: 0\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 64,\n\t\t\t\t\t\tname: \"E\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\tvelocity: .3779527559055118,\n\t\t\t\t\ttype: \"noteoff\",\n\t\t\t\t\ttimestamp: 511.90500000002794\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 60,\n\t\t\t\t\t\tname: \"C\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\ttype: \"noteon\",\n\t\t\t\t\tvelocity: .5275590551181102,\n\t\t\t\t\ttimestamp: 535.8800000001211\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 60,\n\t\t\t\t\t\tname: \"C\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\tvelocity: .33858267716535434,\n\t\t\t\t\ttype: \"noteoff\",\n\t\t\t\t\ttimestamp: 674.9899999999907\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 60,\n\t\t\t\t\t\tname: \"C\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\ttype: \"noteon\",\n\t\t\t\t\tvelocity: .5590551181102362,\n\t\t\t\t\ttimestamp: 1070.8800000000047\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 60,\n\t\t\t\t\t\tname: \"C\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\tvelocity: .3464566929133858,\n\t\t\t\t\ttype: \"noteoff\",\n\t\t\t\t\ttimestamp: 1214.8999999999069\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 64,\n\t\t\t\t\t\tname: \"E\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\ttype: \"noteon\",\n\t\t\t\t\tvelocity: .5118110236220472,\n\t\t\t\t\ttimestamp: 1424.9400000000605\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 64,\n\t\t\t\t\t\tname: \"E\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\tvelocity: .2755905511811024,\n\t\t\t\t\ttype: \"noteoff\",\n\t\t\t\t\ttimestamp: 1576.9150000000373\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 62,\n\t\t\t\t\t\tname: \"D\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\ttype: \"noteon\",\n\t\t\t\t\tvelocity: .3937007874015748,\n\t\t\t\t\ttimestamp: 1756.9149999999208\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 62,\n\t\t\t\t\t\tname: \"D\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\tvelocity: .36220472440944884,\n\t\t\t\t\ttype: \"noteoff\",\n\t\t\t\t\ttimestamp: 1926.9899999998743\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 60,\n\t\t\t\t\t\tname: \"C\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\ttype: \"noteon\",\n\t\t\t\t\tvelocity: .5196850393700787,\n\t\t\t\t\ttimestamp: 1970.9600000000792\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 60,\n\t\t\t\t\t\tname: \"C\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\tvelocity: .36220472440944884,\n\t\t\t\t\ttype: \"noteoff\",\n\t\t\t\t\ttimestamp: 2126.009999999893\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 60,\n\t\t\t\t\t\tname: \"C\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\ttype: \"noteon\",\n\t\t\t\t\tvelocity: .5984251968503937,\n\t\t\t\t\ttimestamp: 2502.0050000000047\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 60,\n\t\t\t\t\t\tname: \"C\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\tvelocity: .3858267716535433,\n\t\t\t\t\ttype: \"noteoff\",\n\t\t\t\t\ttimestamp: 2853.920000000042\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 67,\n\t\t\t\t\t\tname: \"G\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\ttype: \"noteon\",\n\t\t\t\t\tvelocity: .6850393700787402,\n\t\t\t\t\ttimestamp: 2875.8649999999907\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tnote: {\n\t\t\t\t\t\tnumber: 67,\n\t\t\t\t\t\tname: \"G\",\n\t\t\t\t\t\toctave: 4\n\t\t\t\t\t},\n\t\t\t\t\tvelocity: .6377952755905512,\n\t\t\t\t\ttype: \"noteoff\",\n\t\t\t\t\ttimestamp: 4497.004999999888\n\t\t\t\t}\n\t\t\t]);\n\t\t}, indicateHeardNotes = (e) => {\n\t\t\tz({\n\t\t\t\ttext: `I hear a ${e.note.name}!`,\n\t\t\t\tstatus: V.ok\n\t\t\t});\n\t\t};\n\t\tF(a, () => {\n\t\t\tt.value?.selectInput(a.value), checkConfigChanged();\n\t\t}), F(o, () => {\n\t\t\tt.value?.selectOutput(o.value), checkConfigChanged();\n\t\t});\n\t\tlet retrieveSettings = async () => {\n\t\t\tlet t = await (await e.user.getCourseInterface(e._id)).getCourseSettings();\n\t\t\tif (t?.midiinput) {\n\t\t\t\tlet e = t.midiinput.toString();\n\t\t\t\tr.value.some((t) => t.value === e) && (a.value = e, c.value = e);\n\t\t\t}\n\t\t\tif (t?.midioutput) {\n\t\t\t\tlet e = t.midioutput.toString();\n\t\t\t\ti.value.some((t) => t.value === e) && (o.value = e, l.value = e);\n\t\t\t}\n\t\t\tt?.keyboardRange && (h.value = t.keyboardRange.toString(), d.value = h.value), t?.lowestNote && (g.value = parseInt(t.lowestNote.toString()), f.value = g.value), t?.highestNote && (_.value = parseInt(t.highestNote.toString()), m.value = _.value), t?.lowestNote && t?.highestNote && !t?.keyboardRange && (d.value = \"custom\"), u.value = !1;\n\t\t}, saveSettings = async () => {\n\t\t\ts.value = !0, (await H().getUserDB().getCourseInterface(e._id)).updateCourseSettings([\n\t\t\t\t{\n\t\t\t\t\tkey: \"midiinput\",\n\t\t\t\t\tvalue: a.value\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"midioutput\",\n\t\t\t\t\tvalue: o.value\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"keyboardRange\",\n\t\t\t\t\tvalue: d.value\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"lowestNote\",\n\t\t\t\t\tvalue: f.value\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tkey: \"highestNote\",\n\t\t\t\t\tvalue: m.value\n\t\t\t\t}\n\t\t\t]), c.value = a.value, l.value = o.value, h.value = d.value, g.value = f.value, _.value = m.value, u.value = !1, s.value = !1, z({\n\t\t\t\ttext: \"Settings updated.\",\n\t\t\t\tstatus: V.ok\n\t\t\t});\n\t\t};\n\t\treturn k(async () => {\n\t\t\tinitNoteOptions();\n\t\t\ttry {\n\t\t\t\tt.value = await p.instance(), n.value = t.value.state === \"ready\" || t.value.state === \"nodevice\";\n\t\t\t} catch (e) {\n\t\t\t\tconsole.log(`Error on midi Init: ${e}`), n.value = !1;\n\t\t\t}\n\t\t\tn.value && (t.value?.addNoteonListenter(indicateHeardNotes), t.value ? (r.value = t.value.inputs.filter((e) => e.state === \"connected\").map((e) => ({\n\t\t\t\ttitle: `${e.manufacturer}: ${e.name}`,\n\t\t\t\tvalue: e.id\n\t\t\t})), i.value = t.value?.outputs.filter((e) => e.state === \"connected\").map((e) => ({\n\t\t\t\ttitle: `${e.manufacturer}: ${e.name}`,\n\t\t\t\tvalue: e.id\n\t\t\t}))) : (r.value = [{\n\t\t\t\ttitle: \"No inputs available\",\n\t\t\t\tvalue: \"\"\n\t\t\t}], i.value = [{\n\t\t\t\ttitle: \"No outputs available\",\n\t\t\t\tvalue: \"\"\n\t\t\t}]), await retrieveSettings(), !a.value && r.value.length > 0 && (a.value = r.value[0].value), !o.value && i.value.length > 0 && (o.value = i.value[0].value));\n\t\t}), {\n\t\t\tmidiSupported: n,\n\t\t\tinputs: r,\n\t\t\toutputs: i,\n\t\t\tselectedInput: a,\n\t\t\tselectedOutput: o,\n\t\t\tupdatePending: s,\n\t\t\tplaySound,\n\t\t\tsaveSettings,\n\t\t\tconfigChanged: u,\n\t\t\tlowestNote: f,\n\t\t\thighestNote: m,\n\t\t\tkeyboardRangeOptions: y,\n\t\t\tselectedKeyboardRange: d,\n\t\t\tnoteOptions: v,\n\t\t\tupdateCustomRangeFromPreset,\n\t\t\tupdateRangeAndCheckChanges\n\t\t};\n\t}\n}), Q = {\n\tkey: 0,\n\tclass: \"custom-range-inputs d-flex gap-4\"\n}, ue = { class: \"d-flex justify-space-between mt-3\" }, de = { key: 1 };\nfunction _sfc_render(e, t, n, r, i, a) {\n\tlet o = N(\"v-toolbar-title\"), s = N(\"v-toolbar\"), c = N(\"v-select\"), l = N(\"v-divider\"), u = N(\"piano-range-visualizer\"), d = N(\"v-btn\"), f = N(\"v-form\"), p = N(\"v-card-text\"), m = N(\"v-card\");\n\treturn A(), x(m, null, {\n\t\tdefault: I(() => [E(s, { dense: \"\" }, {\n\t\t\tdefault: I(() => [E(o, null, {\n\t\t\t\tdefault: I(() => t[5] ||= [T(\"Configure Midi Device\")]),\n\t\t\t\t_: 1\n\t\t\t})]),\n\t\t\t_: 1\n\t\t}), E(p, null, {\n\t\t\tdefault: I(() => [e.midiSupported ? (A(), x(f, {\n\t\t\t\tkey: 0,\n\t\t\t\tonsubmit: \"return false;\"\n\t\t\t}, {\n\t\t\t\tdefault: I(() => [\n\t\t\t\t\tE(c, {\n\t\t\t\t\t\tmodelValue: e.selectedInput,\n\t\t\t\t\t\t\"onUpdate:modelValue\": t[0] ||= (t) => e.selectedInput = t,\n\t\t\t\t\t\titems: e.inputs,\n\t\t\t\t\t\tlabel: \"Select Input\",\n\t\t\t\t\t\thint: \"Play some notes on your input device to test the connection\"\n\t\t\t\t\t}, null, 8, [\"modelValue\", \"items\"]),\n\t\t\t\t\tE(c, {\n\t\t\t\t\t\tmodelValue: e.selectedOutput,\n\t\t\t\t\t\t\"onUpdate:modelValue\": t[1] ||= (t) => e.selectedOutput = t,\n\t\t\t\t\t\titems: e.outputs,\n\t\t\t\t\t\tlabel: \"Select Output\"\n\t\t\t\t\t}, null, 8, [\"modelValue\", \"items\"]),\n\t\t\t\t\tE(l, { class: \"my-4\" }),\n\t\t\t\t\tt[8] ||= w(\"h3\", { class: \"text-subtitle-1 mb-2\" }, \"Keyboard Range\", -1),\n\t\t\t\t\tE(c, {\n\t\t\t\t\t\tmodelValue: e.selectedKeyboardRange,\n\t\t\t\t\t\t\"onUpdate:modelValue\": [t[2] ||= (t) => e.selectedKeyboardRange = t, e.updateCustomRangeFromPreset],\n\t\t\t\t\t\titems: e.keyboardRangeOptions,\n\t\t\t\t\t\tlabel: \"Select Keyboard Range\"\n\t\t\t\t\t}, null, 8, [\n\t\t\t\t\t\t\"modelValue\",\n\t\t\t\t\t\t\"items\",\n\t\t\t\t\t\t\"onUpdate:modelValue\"\n\t\t\t\t\t]),\n\t\t\t\t\te.selectedKeyboardRange === \"custom\" ? (A(), C(\"div\", Q, [E(c, {\n\t\t\t\t\t\tmodelValue: e.lowestNote,\n\t\t\t\t\t\t\"onUpdate:modelValue\": [t[3] ||= (t) => e.lowestNote = t, e.updateRangeAndCheckChanges],\n\t\t\t\t\t\titems: e.noteOptions,\n\t\t\t\t\t\tlabel: \"Lowest Note\"\n\t\t\t\t\t}, null, 8, [\n\t\t\t\t\t\t\"modelValue\",\n\t\t\t\t\t\t\"items\",\n\t\t\t\t\t\t\"onUpdate:modelValue\"\n\t\t\t\t\t]), E(c, {\n\t\t\t\t\t\tmodelValue: e.highestNote,\n\t\t\t\t\t\t\"onUpdate:modelValue\": [t[4] ||= (t) => e.highestNote = t, e.updateRangeAndCheckChanges],\n\t\t\t\t\t\titems: e.noteOptions,\n\t\t\t\t\t\tlabel: \"Highest Note\"\n\t\t\t\t\t}, null, 8, [\n\t\t\t\t\t\t\"modelValue\",\n\t\t\t\t\t\t\"items\",\n\t\t\t\t\t\t\"onUpdate:modelValue\"\n\t\t\t\t\t])])) : S(\"\", !0),\n\t\t\t\t\tE(u, {\n\t\t\t\t\t\t\"lowest-note\": e.lowestNote,\n\t\t\t\t\t\t\"highest-note\": e.highestNote\n\t\t\t\t\t}, null, 8, [\"lowest-note\", \"highest-note\"]),\n\t\t\t\t\tw(\"div\", ue, [E(d, {\n\t\t\t\t\t\tcolor: \"primary\",\n\t\t\t\t\t\tonClick: e.playSound\n\t\t\t\t\t}, {\n\t\t\t\t\t\tdefault: I(() => t[6] ||= [T(\"Test midi output\")]),\n\t\t\t\t\t\t_: 1\n\t\t\t\t\t}, 8, [\"onClick\"]), E(d, {\n\t\t\t\t\t\tloading: e.updatePending,\n\t\t\t\t\t\tdisabled: !e.configChanged && !e.updatePending,\n\t\t\t\t\t\tcolor: \"info\",\n\t\t\t\t\t\tclass: \"save-button\",\n\t\t\t\t\t\tonClick: e.saveSettings\n\t\t\t\t\t}, {\n\t\t\t\t\t\tdefault: I(() => t[7] ||= [T(\" Save these settings \")]),\n\t\t\t\t\t\t_: 1\n\t\t\t\t\t}, 8, [\n\t\t\t\t\t\t\"loading\",\n\t\t\t\t\t\t\"disabled\",\n\t\t\t\t\t\t\"onClick\"\n\t\t\t\t\t])])\n\t\t\t\t]),\n\t\t\t\t_: 1\n\t\t\t})) : (A(), C(\"div\", de, t[9] ||= [w(\"p\", null, \"This quilt requires a midi input device, which is not supported by this browser.\", -1), w(\"div\", null, [w(\"p\", null, \"Try one of the following browsers:\"), w(\"ul\", null, [\n\t\t\t\tw(\"li\", null, [w(\"a\", { href: \"https://www.google.com/chrome/\" }, \"Google Chrome\")]),\n\t\t\t\tw(\"li\", null, [w(\"a\", { href: \"https://www.microsoft.com/edge\" }, \"Microsoft Edge\")]),\n\t\t\t\tw(\"li\", null, [w(\"a\", { href: \"https://brave.com/\" }, \"Brave\")])\n\t\t\t])], -1)]))]),\n\t\t\t_: 1\n\t\t})]),\n\t\t_: 1\n\t});\n}\nvar fe = /* @__PURE__ */ i(le, [[\"render\", _sfc_render], [\"__scopeId\", \"data-v-6ee9020f\"]]), pe = ee;\nasync function loadSubcourse(e) {\n\tlet t;\n\tswitch (e) {\n\t\tcase \"chess\":\n\t\t\tt = await import(\"./chess-Lfm7Fsvs.js\");\n\t\t\tbreak;\n\t\tcase \"french\":\n\t\t\tt = await import(\"./french-evUMlbbq.js\");\n\t\t\tbreak;\n\t\tcase \"math\":\n\t\t\tt = await import(\"./math-DR3fXDcX.js\");\n\t\t\tbreak;\n\t\tcase \"piano\":\n\t\t\tt = await import(\"./piano-BN5Btq91.js\");\n\t\t\tbreak;\n\t\tcase \"pitch\":\n\t\t\tt = await import(\"./pitch-Dn0iNqiS.js\");\n\t\t\tbreak;\n\t\tcase \"sightSing\":\n\t\t\tt = await import(\"./sightsing-CJX3k0Fd.js\");\n\t\t\tbreak;\n\t\tcase \"typing\":\n\t\t\tt = await import(\"./typing-k-ojjO7G.js\");\n\t\t\tbreak;\n\t\tcase \"wordWork\":\n\t\t\tt = await import(\"./word-work-Dd6tIKrt.js\");\n\t\t\tbreak;\n\t}\n\tlet n = t.default;\n\treturn $.courses.find((e) => e.name === n.name) || $.courses.push(n), n;\n}\nasync function loadAllSubcourses() {\n\tawait Promise.all([\n\t\t\"chess\",\n\t\t\"french\",\n\t\t\"math\",\n\t\t\"piano\",\n\t\t\"pitch\",\n\t\t\"sightSing\",\n\t\t\"typing\",\n\t\t\"wordWork\"\n\t].map((e) => loadSubcourse(e)));\n}\nvar AllCourseWare = class {\n\tcourseWareList;\n\tget courses() {\n\t\treturn this.courseWareList;\n\t}\n\tconstructor(e) {\n\t\tthis.courseWareList = e;\n\t}\n\tgetCourseWare(e) {\n\t\treturn this.courseWareList.find((t) => t.name === e);\n\t}\n\tcachedRawViews = null;\n\tallViewsRaw() {\n\t\tif (!this.cachedRawViews) {\n\t\t\tlet e = this.allViews();\n\t\t\tthis.cachedRawViews = Object.fromEntries(Object.entries(e).map(([e, t]) => [e, O(t)]));\n\t\t}\n\t\treturn this.cachedRawViews;\n\t}\n\tallViews() {\n\t\tlet e = {};\n\t\treturn this.courseWareList.forEach((t) => {\n\t\t\tObject.assign(e, t.allViewsMap);\n\t\t}), e;\n\t}\n\tgetView(e) {\n\t\tlet t;\n\t\tt = typeof e == \"string\" ? B.getViewDescriptor(e) : e;\n\t\tlet n = this.getCourseWare(t.course);\n\t\tif (n) {\n\t\t\tlet e = n.getQuestion(t.questionType);\n\t\t\tif (e) {\n\t\t\t\tlet r = e.views.find((e) => e.name === t.view);\n\t\t\t\tif (r) return r;\n\t\t\t\tthrow console.error(`QuestionView ${t.view} not found in course ${t.course}\n\n descriptor: ${JSON.stringify(t)}\n\n course: ${n.name}\n question: ${e.name}\n views: ${e.views.map((e) => e.name).join(\", \")}\n `), Error(`view ${t.view} does not exist.`);\n\t\t\t} else throw console.error(`Question ${t.questionType} not found in course ${t.course}\n\n descriptor: ${JSON.stringify(t)}\n\n course: ${n.name}\n questions: ${n.questions.map((e) => e.name).join(\", \")}\n `), Error(`question ${t.questionType} does not exist.`);\n\t\t} else throw console.error(`Course ${t.course} not found.\n\n descriptor: ${JSON.stringify(t)}`), Error(`course ${t.course} does not exist.`);\n\t}\n\ttoString() {\n\t\tlet e = \"\";\n\t\treturn this.courses.forEach((t) => {\n\t\t\te += `Course: ${t.name}\\n`, t.questions.forEach((t) => {\n\t\t\t\te += ` Question: ${t.name}\\n`, t.views.forEach((t) => {\n\t\t\t\t\te += ` View: ${t.name}\\n`;\n\t\t\t\t});\n\t\t\t});\n\t\t}), e;\n\t}\n\tallDataShapesRaw() {\n\t\tlet e = [];\n\t\treturn this.courseWareList.forEach((t) => {\n\t\t\tt.questions.forEach((t) => {\n\t\t\t\tt.dataShapes.forEach((t) => {\n\t\t\t\t\te.includes(t) || e.push(t);\n\t\t\t\t});\n\t\t\t});\n\t\t}), e;\n\t}\n\tallDataShapes() {\n\t\tlet e = [];\n\t\treturn this.courseWareList.forEach((t) => {\n\t\t\tt.questions.forEach((n) => {\n\t\t\t\tn.dataShapes.forEach((r) => {\n\t\t\t\t\te.findIndex((e) => e.course === t.name && e.dataShape === r.name) === -1 && e.push({\n\t\t\t\t\t\tcourse: t.name,\n\t\t\t\t\t\tdataShape: r.name,\n\t\t\t\t\t\tdisplayable: n\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t}), e;\n\t}\n\tgetDataShape(e) {\n\t\tlet t;\n\t\tif (this.getCourseWare(e.course).questions.forEach((n) => {\n\t\t\tn.dataShapes.forEach((n) => {\n\t\t\t\tn.name === e.dataShape && (t = n);\n\t\t\t});\n\t\t}), t) return t;\n\t\tthrow Error(`DataShape ${B.getDataShapeString(e)} not found`);\n\t}\n}, $ = new AllCourseWare([]);\n//#endregion\nexport { AllCourseWare, r as BlanksCard, t as BlanksCardDataShapes, a as CourseWare, L as Displayable, fe as MidiConfig, R as Question, p as SkMidi, d as SyllableSeqVis, u as SyllableSequence, $ as allCourseWare, o as chess, U as defaultCourse, l as eventsToSyllableSequence, s as french, n as gradeSpellingAttempt, loadAllSubcourses, loadSubcourse, c as math, m as piano, h as pitch, g as sightSing, f as transposeSyllableSeq, _ as typing, pe as useQuestionView, te as useViewable, v as wordWork };\n\n//# sourceMappingURL=index.mjs.map"],"file":"dist-CAHkbl3M.js"}
@@ -0,0 +1 @@
1
+ import"./vue.runtime.esm-bundler--Fxmd6l9.js";import"./MarkdownRenderer-borh39Lq.js";import"./moment-DbT30ZpG.js";import"./dist-BsRvt0gH.js";import"./contentSource-DwznMSMs.js";import"./dist-Dp6eBE2S.js";import"./CourseWare-BTFRjgBR-DBp_fIwH.js";import"./PipelineDebugger-BHaqzqZw.js";import"./eloDistance-BV7vfiK5.js";import"./chess-E2uOAyQS-BZi0vihz.js";import"./french-Dk7YG8Td-CD7Hms2j.js";import"./math-D_8HiEQR-E4QDLrWp.js";import"./piano-DF1g6yaX-Ck3BH5EK.js";import"./pitch-CgGJFkZ1-Dd0LzmEe.js";import"./sightsing-BFQ7HRig-DV69ELZf.js";import"./typing-BevtfWlp-CvStu5BY.js";import"./word-work-BOnRlZgd-CCGZdwyf.js";import{a as e,r as t,t as n}from"./dist-CAHkbl3M.js";export{n as allCourseWare,t as defaultCourse,e as loadAllSubcourses};
@@ -0,0 +1 @@
1
+ import"./moment-DbT30ZpG.js";import{z as e}from"./contentSource-DwznMSMs.js";import"./dist-Dp6eBE2S.js";import"./PipelineDebugger-BHaqzqZw.js";import"./userDBKeys-DYLGKnVC.js";import"./srs-DOsG9Y-i.js";import"./eloDistance-BV7vfiK5.js";import"./UserDBDebugger-DPqlc4O_.js";export{e as CourseLookup};
@@ -0,0 +1,64 @@
1
+ import"./chunk-D6hFPZc3.js";import{t as e}from"./moment-DbT30ZpG.js";import{A as t,C as n,E as r,F as i,H as a,K as o,R as s,n as c}from"./contentSource-DwznMSMs.js";import{t as l}from"./tagRoles-jR-PJAgj.js";import{t as u}from"./defineProperty-y9rbOPYz.js";import{a as d,n as f,o as p,r as m,s as h}from"./elo-B5qCwvSC.js";import{C as g,D as _,E as v,c as y,i as b,k as x,p as S,r as C,w}from"./PipelineDebugger-BHaqzqZw.js";import{m as T,o as E,s as D}from"./userDBKeys-DYLGKnVC.js";function displayableDataToViewData(e){let t={};return e.data.forEach(e=>{t[e.name]=e.data}),e._attachments&&Object.getOwnPropertyNames(e._attachments).forEach(n=>{e._attachments&&(t[n]=e._attachments[n].data)}),t}function makeStudySessionId(e,t,n){return`${D[E.STUDY_SESSION]}::${e}::${t}::${n}`}function newSessionId(){return`session-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}var QuotaRoundRobinMixer=class{mix(e,t){if(e.length===0)return[];let n=Math.ceil(t/e.length),r=e.map(e=>[...e.weighted].sort((e,t)=>t.score-e.score).slice(0,n));for(let e=r.length-1;e>0;e--){let t=Math.floor(Math.random()*(e+1));[r[e],r[t]]=[r[t],r[e]]}let i=[],a=0,o=Array(r.length).fill(0);for(;i.length<t&&a<r.length;){a=0;for(let e=0;e<r.length&&!(i.length>=t);e++)o[e]<r[e].length?(i.push(r[e][o[e]]),o[e]++):a++}return i}},O=10,k=[];function buildSourceSummary(e,t,n){let r=e.weighted.map(e=>e.score),i=e.weighted.filter(e=>S(e)===`review`).length,a=e.weighted.filter(e=>S(e)===`new`).length;return{sourceIndex:e.sourceIndex,sourceId:t,sourceName:n,totalCards:e.weighted.length,reviewCount:i,newCount:a,topScore:r.length>0?Math.max(...r):0,bottomScore:r.length>0?Math.min(...r):0,scoreRange:r.length>0?[Math.min(...r),Math.max(...r)]:[0,0],avgScore:r.length>0?r.reduce((e,t)=>e+t,0)/r.length:0}}function buildSourceBreakdown(e,t,n){let r=n.filter(t=>t.courseId===e),i=r.filter(e=>e.selected);return{sourceId:e,sourceName:t,reviewsProvided:r.filter(e=>e.origin===`review`).length,newProvided:r.filter(e=>e.origin===`new`).length,reviewsSelected:i.filter(e=>e.origin===`review`).length,newSelected:i.filter(e=>e.origin===`new`).length,totalSelected:i.length,selectionRate:r.length>0?i.length/r.length*100:0}}function captureMixerRun(e,t,n,r,i,a,o){let s=t.map((e,t)=>buildSourceSummary(e,n[t]||`source-${t}`,r[t])),c=new Set(o.map(e=>e.cardId)),l=new Map;t.forEach(e=>{let t=[...e.weighted].sort((e,t)=>t.score-e.score),r=new Map;t.forEach((e,t)=>{r.set(e.cardId,t+1)}),l.set(n[e.sourceIndex]||`source-${e.sourceIndex}`,r)});let u=new Map;o.forEach((e,t)=>{u.set(e.cardId,t+1)});let d=new Map;t.forEach(e=>{e.weighted.forEach(e=>{d.set(e.cardId,e)})});let f=Array.from(d.values()).map(e=>({cardId:e.cardId,courseId:e.courseId,origin:S(e),score:e.score,sourceIndex:t.findIndex(t=>t.weighted.some(t=>t.cardId===e.cardId)),selected:c.has(e.cardId),rankInSource:l.get(e.courseId)?.get(e.cardId),rankInMix:u.get(e.cardId)})),p=Array.from(new Set(n.filter(e=>e))).map((e,t)=>buildSourceBreakdown(e,r[t],f)),m={runId:`mix-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,timestamp:new Date,mixerType:e,requestedLimit:i,quotaPerSource:a,sourceSummaries:s,cards:f,finalCount:o.length,reviewsSelected:o.filter(e=>S(e)===`review`).length,newSelected:o.filter(e=>S(e)===`new`).length,sourceBreakdowns:p};k.unshift(m),k.length>O&&k.pop()}function printMixerSummary(e){console.group(`🎨 Mixer Run: ${e.mixerType}`),x.print(`Run ID: ${e.runId}`),x.print(`Time: ${e.timestamp.toISOString()}`),x.print(`Config: limit=${e.requestedLimit}${e.quotaPerSource?`, quota/source=${e.quotaPerSource}`:``}`),console.group(`📥 Input: ${e.sourceSummaries.length} sources`);for(let t of e.sourceSummaries)x.print(` ${t.sourceName||t.sourceId}: ${t.totalCards} cards (${t.reviewCount} reviews, ${t.newCount} new)`),x.print(` Score range: [${t.scoreRange[0].toFixed(2)}, ${t.scoreRange[1].toFixed(2)}], avg: ${t.avgScore.toFixed(2)}`);console.groupEnd(),console.group(`📤 Output: ${e.finalCount} cards selected (${e.reviewsSelected} reviews, ${e.newSelected} new)`);for(let t of e.sourceBreakdowns){let e=t.sourceName||t.sourceId;x.print(` ${e}: ${t.totalSelected} selected (${t.reviewsSelected} reviews, ${t.newSelected} new) - ${t.selectionRate.toFixed(1)}% selection rate`)}console.groupEnd(),console.groupEnd()}var A={get runs(){return[...k]},showRun(e=0){if(k.length===0){x.print(`[Mixer Debug] No runs captured yet.`);return}let t;if(typeof e==`number`){if(t=k[e],!t){x.print(`[Mixer Debug] No run found at index ${e}. History length: ${k.length}`);return}}else if(t=k.find(t=>t.runId.endsWith(e)),!t){x.print(`[Mixer Debug] No run found matching ID '${e}'.`);return}printMixerSummary(t)},showLastMix(){this.showRun(0)},explainSourceBalance(){if(k.length===0){x.print(`[Mixer Debug] No runs captured yet.`);return}let e=k[0];console.group(`⚖️ Source Balance Analysis`),x.print(`Mixer: ${e.mixerType}`),x.print(`Requested limit: ${e.requestedLimit}`),e.quotaPerSource&&x.print(`Quota per source: ${e.quotaPerSource}`),console.group(`Input Distribution:`);for(let t of e.sourceSummaries){let e=t.sourceName||t.sourceId;x.print(`${e}:`),x.print(` Provided: ${t.totalCards} cards (${t.reviewCount} reviews, ${t.newCount} new)`),x.print(` Score range: [${t.scoreRange[0].toFixed(2)}, ${t.scoreRange[1].toFixed(2)}]`)}console.groupEnd(),console.group(`Selection Results:`);for(let t of e.sourceBreakdowns){let e=t.sourceName||t.sourceId;x.print(`${e}:`),x.print(` Selected: ${t.totalSelected}/${t.reviewsProvided+t.newProvided} (${t.selectionRate.toFixed(1)}%)`),x.print(` Reviews: ${t.reviewsSelected}/${t.reviewsProvided}`),x.print(` New: ${t.newSelected}/${t.newProvided}`),t.reviewsProvided>0&&t.reviewsSelected===0&&x.print(` ⚠️ Had reviews but none selected!`),t.totalSelected===0&&t.reviewsProvided+t.newProvided>0&&x.print(` ⚠️ Had cards but none selected!`)}console.groupEnd();let t=e.sourceBreakdowns.map(e=>e.selectionRate),n=t.reduce((e,t)=>e+t,0)/t.length,r=Math.max(...t.map(e=>Math.abs(e-n)));r>20&&(x.print(`\n⚠️ Significant imbalance detected (max deviation: ${r.toFixed(1)}%)`),x.print(`Possible causes:`),x.print(` - Score range differences between sources`),x.print(` - One source has much better quality cards`),x.print(` - Different card availability (reviews vs new)`)),console.groupEnd()},compareScores(){if(k.length===0){x.print(`[Mixer Debug] No runs captured yet.`);return}let e=k[0];console.group(`📊 Score Distribution Comparison`),console.table(e.sourceSummaries.map(e=>({source:e.sourceName||e.sourceId,cards:e.totalCards,min:e.bottomScore.toFixed(3),max:e.topScore.toFixed(3),avg:e.avgScore.toFixed(3),range:(e.topScore-e.bottomScore).toFixed(3)})));let t=e.sourceSummaries.map(e=>e.topScore-e.bottomScore),n=e.sourceSummaries.map(e=>e.avgScore),r=Math.max(...t)-Math.min(...t),i=Math.max(...n)-Math.min(...n);(r>.3||i>.2)&&(x.print(`
2
+ ⚠️ Significant score distribution differences detected`),x.print(`This may cause one source to dominate selection if using global sorting (not quota-based)`)),console.groupEnd()},showCard(e){for(let t of k){let n=t.cards.find(t=>t.cardId===e);if(n){let r=t.sourceSummaries.find(e=>e.sourceIndex===n.sourceIndex);console.group(`🎴 Card: ${e}`),x.print(`Course: ${n.courseId}`),x.print(`Source: ${r?.sourceName||r?.sourceId||`unknown`}`),x.print(`Origin: ${n.origin}`),x.print(`Score: ${n.score.toFixed(3)}`),n.rankInSource&&x.print(`Rank in source: #${n.rankInSource}`),n.rankInMix&&x.print(`Rank in mixed results: #${n.rankInMix}`),x.print(`Selected: ${n.selected?`Yes ✅`:`No ❌`}`),!n.selected&&n.rankInSource&&(x.print(`
3
+ Why not selected:`),t.quotaPerSource&&n.rankInSource>t.quotaPerSource&&x.print(` - Ranked #${n.rankInSource} in source, but quota was ${t.quotaPerSource}`),x.print(` - Check score compared to selected cards using .showRun()`)),console.groupEnd();return}}x.print(`[Mixer Debug] Card '${e}' not found in recent runs.`)},listRuns(){if(k.length===0){x.print(`[Mixer Debug] No runs captured yet.`);return}console.table(k.map(e=>({id:e.runId.slice(-8),time:e.timestamp.toLocaleTimeString(),mixer:e.mixerType,sources:e.sourceSummaries.length,selected:e.finalCount,reviews:e.reviewsSelected,new:e.newSelected})))},export(){let e=JSON.stringify(k,null,2);return x.print(`[Mixer Debug] Run history exported. Copy the returned string or use:`),x.print(` copy(window.skuilder.mixer.export())`),e},clear(){k.length=0,x.print(`[Mixer Debug] Run history cleared.`)},help(){x.print(`
4
+ 🎨 Mixer Debug API
5
+
6
+ Commands:
7
+ .showLastMix() Show summary of most recent mixer run
8
+ .showRun(id|index) Show summary of a specific run (by index or ID suffix)
9
+ .explainSourceBalance() Analyze source balance and selection patterns
10
+ .compareScores() Compare score distributions across sources
11
+ .showCard(cardId) Show mixer decisions for a specific card
12
+ .listRuns() List all captured runs in table format
13
+ .export() Export run history as JSON for bug reports
14
+ .clear() Clear run history
15
+ .runs Access raw run history array
16
+ .help() Show this help message
17
+
18
+ Example:
19
+ window.skuilder.mixer.showLastMix()
20
+ window.skuilder.mixer.explainSourceBalance()
21
+ window.skuilder.mixer.compareScores()
22
+ `)}};function mountMixerDebugger(){if(typeof window>`u`)return;let e=window;e.skuilder=e.skuilder||{},e.skuilder.mixer=A}mountMixerDebugger();var j=null;function registerActiveController(e){j=e}function getActiveController(){return j}var M=`skuilder-session-overlay`,N=300,P=5,F=[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`],I=0,L=null,R=null,z=null,B=0,V=!1,H={supplyQ:!1,failedQ:!1,drawn:!1};function toggleSessionOverlay(){if(typeof document>`u`){x.print(`[Session Overlay] No DOM available (non-browser host); overlay unavailable.`);return}L?(teardown(),x.print(`[Session Overlay] Hidden.`)):(mount(),x.print(`[Session Overlay] Shown. Toggle off with window.skuilder.session.dbgOverlay().`))}function mount(){V=!1,L=document.createElement(`div`),L.id=M,Object.assign(L.style,{position:`fixed`,top:`8px`,left:`8px`,zIndex:`2147483647`,maxWidth:`320px`,maxHeight:`90vh`,overflowY:`auto`,padding:`8px 10px`,background:`rgba(17, 24, 39, 0.92)`,color:`#e5e7eb`,font:`11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace`,borderRadius:`6px`,boxShadow:`0 4px 16px rgba(0,0,0,0.4)`,pointerEvents:`auto`,userSelect:`none`}),document.body.appendChild(L),render(),R=setInterval(render,N)}function teardown(){R!==null&&(clearInterval(R),R=null),L?.parentNode&&L.parentNode.removeChild(L),L=null}function render(){if(!L)return;I++;let e=getActiveController();if(!e){z=null,L.innerHTML=headerHtml()+(V?``:`<div style="opacity:.65">No active session.</div>`),attachHandlers();return}let t=e.getDebugSnapshot();if(z=t,V){L.innerHTML=headerHtml(),attachHandlers();return}L.innerHTML=headerHtml()+replanHtml(t)+metaHtml(t)+hintsHtml(t.sessionHints)+backlogHtml(t.reviewBacklog)+strategyPressureHtml(t.strategyPressure)+queueHtml(`supplyQ`,`supplyQ`,t.supplyQ)+queueHtml(`failedQ`,`failedQ`,t.failedQ)+drawnHtml(`drawn`,t.drawnCards),attachHandlers()}function attachHandlers(){if(!L)return;L.querySelectorAll(`[data-q]`).forEach(e=>{e.onclick=()=>{let t=e.dataset.q;t&&(H[t]=!H[t],render())}});let e=L.querySelector(`[data-copy]`);e&&(e.onclick=e=>{e.stopPropagation(),copySnapshot()});let t=L.querySelector(`[data-min]`);t&&(t.onclick=e=>{e.stopPropagation(),V=!V,render()})}function copySnapshot(){let e=snapshotToText(z),flash=()=>{B=Date.now()+1200,render()},t=typeof navigator<`u`?navigator.clipboard:void 0;t?.writeText?t.writeText(e).then(flash,e=>{x.warn(`[Session Overlay] Clipboard write failed: ${String(e)}`)}):x.print(`[Session Overlay] Clipboard unavailable; snapshot follows:\n${e}`)}function headerHtml(){let e=Date.now()<B;return`<div style="font-weight:600;color:#93c5fd;margin-bottom:${V?0:4}px">${`<span data-copy style="cursor:pointer;float:right;font-weight:400;color:${e?`#86efac`:`#93c5fd`};border:1px solid currentColor;border-radius:4px;padding:0 4px;line-height:1.3">${e?`✓ copied`:`⎘ copy`}</span>`}${`<span data-min title="${V?`Restore`:`Minify`}" style="cursor:pointer;float:right;font-weight:400;color:#93c5fd;border:1px solid currentColor;border-radius:4px;padding:0 5px;margin-right:4px;line-height:1.3">${V?`▢`:`—`}</span>`}⚙ SessionController</div>`}function replanHtml(e){return e.replanActive?`<div style="margin-bottom:6px;color:#fde047">${F[I%F.length]} replanning <span style="opacity:.85">[${esc(e.replanLabel??`(auto)`)}]</span></div>`:`<div style="margin-bottom:6px;opacity:.45">○ idle</div>`}function metaHtml(e){return`<div style="margin-bottom:6px">${[`time ${formatTime(e.secondsRemaining)}${e.hasCardGuarantee?` · <span style="color:#fbbf24">guarantee ${e.minCardsGuarantee}</span>`:``}`,`well-indicated left: ${e.wellIndicatedRemaining}`,`current: ${e.currentCard?esc(e.currentCard):`<span style="opacity:.6">—</span>`}`].map(e=>`<div>${e}</div>`).join(``)}</div>`}function hintsHtml(e){let t=[];return e&&(e.boostTags&&Object.keys(e.boostTags).length&&t.push(`boost: `+Object.entries(e.boostTags).map(([e,t])=>`${esc(e)}<span style="opacity:.6">×${t}</span>`).join(`, `)),e.boostCards&&Object.keys(e.boostCards).length&&t.push(`boostCards: `+Object.entries(e.boostCards).map(([e,t])=>`${esc(e)}<span style="opacity:.6">×${t}</span>`).join(`, `)),e.requireCards?.length&&t.push(`require: ${e.requireCards.map(esc).join(`, `)}`),e.requireTags?.length&&t.push(`requireTags: ${e.requireTags.map(esc).join(`, `)}`),e.excludeTags?.length&&t.push(`exclude: ${e.excludeTags.map(esc).join(`, `)}`),e.excludeCards?.length&&t.push(`excludeCards: ${e.excludeCards.map(esc).join(`, `)}`)),`<div style="margin-bottom:6px"><div style="color:#86efac">sessionHints</div>${t.length?t.map(e=>`<div style="margin-left:6px">${e}</div>`).join(``):`<div style="margin-left:6px;opacity:.6">none</div>`}</div>`}function backlogHtml(e){return e.length?`<div style="margin-bottom:6px"><div style="color:#93c5fd">review backpressure</div>${e.map(e=>{let t=e.backlogMultiplier>=3,n=e.backlogMultiplier<=1?`#86efac`:t?`#fca5a5`:`#fcd34d`,r=e.backlogMultiplier>1?`climbing (×${e.backlogGrowthRate.toFixed(2)} per ${e.healthyBacklog} of mass in excess, unbounded)`:`healthy — no pressure`,i=e.reviewMass===null?``:` · mass ${e.reviewMass.toFixed(1)}`,a=e.topReviewScore===null?`—`:e.topReviewScore.toFixed(2),o=e.nextDueIn?` <span style="opacity:.6">· next due ${esc(e.nextDueIn)}</span>`:``;return`<div style="margin-left:6px"><span style="opacity:.7">${esc(e.courseId.slice(0,8))}</span> due ${e.dueNow}/${e.scheduledTotal}${i} <span style="opacity:.6">(healthy mass ${e.healthyBacklog})</span>${o}<div style="margin-left:6px">pressure <span style="color:${n}">×${e.backlogMultiplier.toFixed(2)}</span> <span style="opacity:.6">${r} · top review ${a}</span></div></div>`}).join(``)}</div>`:``}function pressureColor(e,t){return e<=1.001?`#86efac`:t!==void 0&&t>1?(e-1)/(t-1)>=.75?`#fca5a5`:`#fcd34d`:e>=3?`#fca5a5`:`#fcd34d`}function toggleKey(e){return e.replace(/[^\w:.|-]/g,`_`)}function gaugeHtml(e,t){let n=t.max===void 0?``:`<span style="opacity:.5">/${t.max}</span>`,r=t.detail?` <span style="opacity:.6">${esc(t.detail)}</span>`:``,i=`<div style="margin-left:6px">${esc(t.label)} <span style="color:${pressureColor(t.multiplier,t.max)}">×${t.multiplier.toFixed(2)}</span>${n}${r}`,a=t.items??[];if(a.length>0){let n=toggleKey(`sp|${e}|${t.id}`),r=!!H[n],o=r?a:a.slice(0,P);if(i+=`<div style="margin-left:6px">`+o.map(e=>`<div style="white-space:nowrap;opacity:.75">${esc(e.label)}${e.value?` <span style="opacity:.6">${esc(e.value)}</span>`:``}</div>`).join(``),a.length>P){let e=r?`▾ show less`:`… +${a.length-o.length} more`;i+=`<div data-q="${n}" style="cursor:pointer;opacity:.6">${e}</div>`}i+=`</div>`}return i+`</div>`}function strategyPressureHtml(e){return e.length?`<div style="margin-bottom:6px"><div style="color:#fdba74">strategy backpressure</div>${e.map(e=>{let t=`${e.source}:${e.courseId.slice(0,8)}`,n=e.topScore!==null&&e.topScore!==void 0?e.topScore.toFixed(2):`—`,r=e.hintsLabel?`<div style="margin-left:6px;opacity:.6">hints: ${esc(e.hintsLabel)}</div>`:``;return`<div style="margin-left:6px"><span style="opacity:.7">${esc(e.source)} · ${esc(e.courseId.slice(0,8))}</span> <span style="opacity:.6">top score ${n}</span>`+e.gauges.map(e=>gaugeHtml(t,e)).join(``)+r+`</div>`}).join(``)}</div>`:``}function fmtScore(e){return e===void 0?``:Number.isFinite(e)?e.toFixed(2):`REQ`}function queueItemHtml(e){let t=e.origin===`review`?`#93c5fd`:`#fcd34d`,n=fmtScore(e.score),r=`${e.origin===`review`?`r`:`n`}${n?` `+n:``}`;return`${esc(e.cardID)}<span style="color:${t};opacity:.85"> [${r}]</span>`}function queueHtml(e,t,n){let r=n.length>P,i=r&&H[e],a=r?H[e]?`▾ `:`▸ `:``,o=n.dequeueCount?` <span style="opacity:.5">drawn ${n.dequeueCount}</span>`:``,s=r?`cursor:pointer;color:#f9a8d4`:`color:#f9a8d4`,c=`<div${r?` data-q="${e}"`:``} style="${s}">${a}${t}: ${n.length}${o}</div>`;if(!n.cards.length)return c+`<div style="margin:1px 0 6px 6px;opacity:.5">empty</div>`;let l=i?n.cards:n.cards.slice(0,P),u=n.length-l.length,d=`<ol style="margin:2px 0 ${r?2:6}px 0;padding-left:20px">`+l.map(e=>`<li style="white-space:nowrap">${queueItemHtml(e)}</li>`).join(``)+`</ol>`;if(r){let t=i?`▾ show less`:`… +${u} more`;d+=`<div data-q="${e}" style="cursor:pointer;margin:0 0 6px 20px;opacity:.6">${t}</div>`}return c+d}function outcomeGlyph(e){return e===!0?`<span style="color:#86efac">✓</span>`:e===!1?`<span style="color:#fca5a5">✗</span>`:`<span style="opacity:.5">·</span>`}function drawnHtml(e,t){let n=t.length>P,r=n&&H[e],i=n?H[e]?`▾ `:`▸ `:``,a=n?`cursor:pointer;color:#c4b5fd`:`color:#c4b5fd`,o=`<div${n?` data-q="${e}"`:``} style="${a}">${i}drawn: ${t.length}</div>`;if(!t.length)return o+`<div style="margin:1px 0 6px 6px;opacity:.5">none yet</div>`;let s=r?t:t.slice(0,P),c=t.length-s.length,l=`<ol style="margin:2px 0 ${n?2:6}px 0;padding-left:20px">${s.map(e=>{let t=e.attempts>1?`<span style="opacity:.5"> ×${e.attempts}</span>`:``,n=`<span style="opacity:.45"> ${Math.round(e.timeSpentMs/100)/10}s</span>`;return`<li style="white-space:nowrap">${outcomeGlyph(e.correct)} ${esc(e.cardID)}<span style="opacity:.5"> [${esc(e.status)}]</span>${t}${n}</li>`}).join(``)}</ol>`;if(n){let t=r?`▾ show less`:`… +${c} more`;l+=`<div data-q="${e}" style="cursor:pointer;margin:0 0 6px 20px;opacity:.6">${t}</div>`}return o+l}function snapshotToText(e){if(!e)return`SessionController — no active session.`;let t=[];t.push(`=== SessionController ===`),t.push(`time ${formatTime(e.secondsRemaining)}`),e.hasCardGuarantee&&t.push(`guarantee: ${e.minCardsGuarantee}`),t.push(`well-indicated left: ${e.wellIndicatedRemaining}`),t.push(`current: ${e.currentCard??`—`}`),t.push(e.replanActive?`replan: ACTIVE [${e.replanLabel??`(auto)`}]`:`replan: idle`),t.push(``),t.push(`sessionHints:`);let n=e.sessionHints,r=[];if(n&&(n.boostTags&&Object.keys(n.boostTags).length&&r.push(` boost: ${Object.entries(n.boostTags).map(([e,t])=>`${e}×${t}`).join(`, `)}`),n.boostCards&&Object.keys(n.boostCards).length&&r.push(` boostCards: ${Object.entries(n.boostCards).map(([e,t])=>`${e}×${t}`).join(`, `)}`),n.requireCards?.length&&r.push(` require: ${n.requireCards.join(`, `)}`),n.requireTags?.length&&r.push(` requireTags: ${n.requireTags.join(`, `)}`),n.excludeTags?.length&&r.push(` exclude: ${n.excludeTags.join(`, `)}`),n.excludeCards?.length&&r.push(` excludeCards: ${n.excludeCards.join(`, `)}`)),t.push(r.length?r.join(`
23
+ `):` none`),e.reviewBacklog.length){t.push(``),t.push(`review backpressure:`);for(let n of e.reviewBacklog){let e=n.backlogMultiplier>1?`climbing`:`healthy`,r=n.topReviewScore===null?`—`:n.topReviewScore.toFixed(2),i=n.nextDueIn?`, next due ${n.nextDueIn}`:``,a=n.reviewMass===null?``:`, mass ${n.reviewMass.toFixed(1)}`;t.push(` ${n.courseId.slice(0,8)}: due ${n.dueNow}/${n.scheduledTotal}${a} (healthy mass ${n.healthyBacklog})${i}; pressure ×${n.backlogMultiplier.toFixed(2)} ${e}; top review ${r}`)}}if(e.strategyPressure.length){t.push(``),t.push(`strategy backpressure:`);for(let n of e.strategyPressure){let e=n.topScore!==null&&n.topScore!==void 0?n.topScore.toFixed(2):`—`;t.push(` ${n.source} (${n.courseId.slice(0,8)}): top score ${e}`);for(let e of n.gauges){let n=e.max===void 0?``:`/${e.max}`;t.push(` ${e.label} ×${e.multiplier.toFixed(2)}${n}${e.detail?` — ${e.detail}`:``}`);for(let n of e.items??[])t.push(` ${n.label}${n.value?` (${n.value})`:``}`)}n.hintsLabel&&t.push(` hints: ${n.hintsLabel}`)}}let queueText=(e,n)=>{t.push(``),t.push(`${e}: ${n.length} (drawn ${n.dequeueCount})`),n.cards.forEach((e,n)=>{let r=fmtScore(e.score),i=`${e.origin===`review`?`r`:`n`}${r?` `+r:``}`;t.push(` ${n+1}. ${e.cardID} [${i}]`)})};return queueText(`supplyQ`,e.supplyQ),queueText(`failedQ`,e.failedQ),t.push(``),t.push(`drawn: ${e.drawnCards.length}`),e.drawnCards.forEach((e,n)=>{let r=e.correct===!0?`✓`:e.correct===!1?`✗`:`·`,i=`${Math.round(e.timeSpentMs/100)/10}s`;t.push(` ${n+1}. ${r} ${e.cardID} [${e.status}] ×${e.attempts} ${i}`)}),t.join(`
24
+ `)}function formatTime(e){let t=Math.max(0,Math.round(e));return`${Math.floor(t/60)}:${(t%60).toString().padStart(2,`0`)}`}function esc(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`)}var U=null,W=[],G=5;function clearStaleSessionDebugState(){C(),v(),g()}function startSessionTracking(e,t,n){U={sessionId:e,startTime:new Date,initialQueues:{timestamp:new Date,supplyQLength:t,failedQLength:n},presentations:[],queueSnapshots:[]},x.debug(`[SessionDebugger] Started tracking session: ${e}`)}function recordCardPresentation(e,t,n,r,i,a){if(!U){x.warn(`[SessionDebugger] No active session to record presentation`);return}U.presentations.push({timestamp:new Date,sequenceNumber:U.presentations.length+1,cardId:e,courseId:t,courseName:n,origin:r,queueSource:i,score:a})}function snapshotQueues(e,t,n){U&&U.queueSnapshots.push({timestamp:new Date,supplyQLength:e,failedQLength:t,supplyQNext3:n})}function endSessionTracking(){U&&(U.endTime=new Date,W.unshift(U),W.length>G&&W.pop(),x.debug(`[SessionDebugger] Ended session: ${U.sessionId}`),U=null)}function showCurrentQueue(){if(!U){x.print(`[Session Debug] No active session.`);return}let e=U.queueSnapshots[U.queueSnapshots.length-1]||U.initialQueues;console.group(`📊 Current Queue State`),x.print(`Supply Queue: ${e.supplyQLength} cards`),e.supplyQNext3&&e.supplyQNext3.length>0&&x.print(` Next: ${e.supplyQNext3.join(`, `)}`),x.print(`Failed Queue: ${e.failedQLength} cards`),console.groupEnd()}function showPresentationHistory(e=0){let t=e===0&&U?U:W[e];if(!t){x.print(`[Session Debug] No session found at index ${e}`);return}console.group(`📜 Session History: ${t.sessionId}`),x.print(`Started: ${t.startTime.toLocaleTimeString()}`),t.endTime&&x.print(`Ended: ${t.endTime.toLocaleTimeString()}`),x.print(`Cards presented: ${t.presentations.length}`),t.presentations.length>0&&console.table(t.presentations.map(e=>({"#":e.sequenceNumber,course:e.courseName||e.courseId.slice(0,8),origin:e.origin,queue:e.queueSource,score:e.score?.toFixed(3)||`-`,time:e.timestamp.toLocaleTimeString()}))),console.groupEnd()}function showInterleaving(e=0){let t=e===0&&U?U:W[e];if(!t){x.print(`[Session Debug] No session found at index ${e}`);return}console.group(`🔀 Interleaving Analysis`);let n=new Map,r=new Map;if(t.presentations.forEach(e=>{let t=e.courseName||e.courseId;n.set(t,(n.get(t)||0)+1),r.has(t)||r.set(t,{review:0,new:0,failed:0});let i=r.get(t);i[e.origin]++}),x.print(`Course distribution:`),console.table(Array.from(n.entries()).map(([e,n])=>{let i=r.get(e);return{course:e,total:n,reviews:i.review,new:i.new,failed:i.failed,percentage:(n/t.presentations.length*100).toFixed(1)+`%`}})),t.presentations.length>0){x.print(`
25
+ Presentation sequence (first 20):`);let e=t.presentations.slice(0,20).map((e,t)=>`${t+1}. ${e.courseName||e.courseId.slice(0,8)} (${e.origin})`).join(`
26
+ `);x.print(e)}let i=0,a=1,o=t.presentations[0]?.courseId;for(let e=1;e<t.presentations.length;e++)t.presentations[e].courseId===o?(a++,i=Math.max(i,a)):(o=t.presentations[e].courseId,a=1);i>3&&(x.print(`\n⚠️ Detected clustering: max ${i} cards from same course in a row`),x.print(`This suggests cards are sorted by score rather than round-robin by course.`)),console.groupEnd()}var K={get sessions(){return[...W]},get active(){return U},showQueue(){showCurrentQueue()},dbgOverlay(){toggleSessionOverlay()},showHistory(e=0){showPresentationHistory(e)},showInterleaving(e=0){showInterleaving(e)},listSessions(){if(U&&x.print(`Active session: ${U.sessionId} (${U.presentations.length} cards presented)`),W.length===0){x.print(`[Session Debug] No completed sessions in history.`);return}console.table(W.map((e,t)=>({index:t,id:e.sessionId.slice(-8),started:e.startTime.toLocaleTimeString(),ended:e.endTime?.toLocaleTimeString()||`incomplete`,cards:e.presentations.length})))},export(){let e={active:U,history:W},t=JSON.stringify(e,null,2);return x.print(`[Session Debug] Session data exported. Copy the returned string or use:`),x.print(` copy(window.skuilder.session.export())`),t},clear(){W.length=0,x.print(`[Session Debug] Session history cleared.`)},help(){x.print(`
27
+ 🎯 Session Debug API
28
+
29
+ Commands:
30
+ .dbgOverlay() Toggle the pinned live overlay (queues, hints, timer)
31
+ .showQueue() Show current queue state (active session only)
32
+ .showHistory(index?) Show presentation history (0=current/last, 1=previous, etc)
33
+ .showInterleaving(index?) Analyze course interleaving pattern
34
+ .listSessions() List all tracked sessions
35
+ .export() Export session data as JSON for bug reports
36
+ .clear() Clear session history
37
+ .sessions Access raw session history array
38
+ .active Access active session (if any)
39
+ .help() Show this help message
40
+
41
+ Example:
42
+ window.skuilder.session.showHistory()
43
+ window.skuilder.session.showInterleaving()
44
+ window.skuilder.session.showQueue()
45
+ `)}};function mountSessionDebugger(){if(typeof window>`u`)return;let e=window;e.skuilder=e.skuilder||{},e.skuilder.session=K}mountSessionDebugger();var SrsService=class{constructor(e){u(this,`user`,void 0),this.user=e}removeReview(e){x.info(`[SrsService] Removing orphaned scheduled review: ${e}`),this.user.removeScheduledCardReview(e)}async scheduleReview(t,r){let i=n(this.user,t),a=e.utc().add(i,`seconds`);c(r)&&(x.info(`[SrsService] Removing previously scheduled review for: ${r.cardID}`),this.user.removeScheduledCardReview(r.reviewID)),this.user.scheduleCardReview({user:this.user.getUsername(),course_id:t.courseID,card_id:t.cardID,time:a,scheduledFor:r.contentSourceType,schedulingAgentId:r.contentSourceID})}};function currentRecord(e){return e.length?e[e.length-1]:null}function isFirstAttempt(e){let t=currentRecord(e);if(!t)return!1;let n=t.priorAttemps;return typeof n==`number`?n===0:e.length===1}function recordTagPresentations(e,t,n,r,i){if(!isFirstAttempt(n))return[];let a=currentRecord(n)?.isCorrect===!0,o=[];for(let[n,s]of Object.entries(t)){if(n===`_global`||typeof s!=`number`)continue;let t=e.tags[n]??{score:e.global.score,count:0},c={at:i,ok:a,perf:s,card:r};e.tags[n]=p(t,c),o.push(n)}return o}function withCountOnlyRoles(e,t){let n={...e},r=[];for(let[t,i]of Object.entries(e))t===`_global`||i===null||!l(t)||(n[t]=null,r.push(t));return r.length&&x.warn(`[EloService] ${t} sent scores for bookkeeping tags [${r.join(`, `)}]; counted, not graded`),n}var EloService=class{constructor(e,t){u(this,`dataLayer`,void 0),u(this,`user`,void 0),u(this,`qaPatterns`,new Map),this.dataLayer=e,this.user=t}async isQaUser(e){let t=e.getCourseID(),n=this.qaPatterns.get(t);return n||(n=e.getCourseConfig().then(e=>e.qaUsernamePattern?new RegExp(e.qaUsernamePattern,`i`):null).catch(e=>(x.warn(`[EloService] No QA username pattern for ${t}: ${e}`),null)),this.qaPatterns.set(t,n)),(await n)?.test(this.user.getUsername())??!1}async updateUserAndCardElo(e,t,n,r,i,a){a&&x.warn(`k value interpretation not currently implemented`);let o=this.dataLayer.getCourseDB(i.card.course_id),s=r.courses.find(e=>e.courseID===t);if(!s)return x.error(`[EloService] No registration for course ${t} on user's registration doc — skipping ELO update for card ${n}. (Is the user registered for this course?)`),null;let c=h(s.elo),u=(await o.getCardEloData([i.card.card_id]))[0];if(u&&c){let r=!await this.isQaUser(o),i=c.global.score,a=u.global.score,d=Object.keys(u.tags),p={};for(let e of d)p[e]=c.tags[e]?.score??c.global.score;let m=f(c,u,e);s.elo=m.userElo;let h={};for(let t of d){let n=l(t);h[t]={before:p[t],after:n?p[t]:m.userElo.tags[t].score,score:n?null:e}}let g={cardId:n,at:new Date().toISOString(),userScore:e,global:{before:i,after:m.userElo.global.score},card:{before:a,after:r?m.cardElo.global.score:a},...d.length?{tags:h}:{}};r||x.info(`[EloService] QA account: card ELO for ${n} not written`);let _=await Promise.allSettled([this.user.updateUserElo(t,m.userElo),r?o.updateCardElo(n,m.cardElo):Promise.resolve(null)]),v=_[0].status===`fulfilled`,y=_[1].status===`fulfilled`;if(v&&y){let e=_[0].value,t=_[1].value;e.ok&&t&&t.ok&&x.info(`[EloService] Updated ELOS:
46
+ \tUser: ${JSON.stringify(m.userElo)})
47
+ \tCard: ${JSON.stringify(m.cardElo)})
48
+ `)}else x.warn(`[EloService] Partial ELO update:
49
+ \tUser ELO update: ${v?`SUCCESS`:`FAILED`}
50
+ \tCard ELO update: ${y?`SUCCESS`:`FAILED`}`),!v&&_[0].status===`rejected`&&x.error(`[EloService] User ELO update error:`,_[0].reason),!y&&_[1].status===`rejected`&&x.error(`[EloService] Card ELO update error:`,_[1].reason);return g}return null}async updateUserAndCardEloPerTag(e,t,n,r,i){let a=this.dataLayer.getCourseDB(i.card.course_id),o=r.courses.find(e=>e.courseID===t);if(!o)return x.error(`[EloService] No registration for course ${t} on user's registration doc — skipping per-tag ELO update for card ${n}. (Is the user registered for this course?)`),null;let s=h(o.elo),[c,u]=await Promise.all([a.getCardEloData([i.card.card_id]),a.getAppliedTagsBatch([n])]),d=c[0],f=u.get(n)??[],p=withCountOnlyRoles(e,n),g={...p},_=e._global;for(let e of f)e in g||(g[e]=l(e)?null:_);if(d&&s){let e=!await this.isQaUser(a),r=s.global.score,c=d.global.score,l=Object.keys(g).filter(e=>e!==`_global`),u={};for(let e of l)u[e]=s.tags[e]?.score??s.global.score;let f=m(s,d,g),h=new Date().toISOString(),v=recordTagPresentations(f.userElo,p,i.records,n,h);v.length&&x.info(`[EloService] recent-presentation entries for ${n}: [${v.join(`, `)}]`),o.elo=f.userElo;let y={};for(let e of l){let t=g[e],n=t===null?u[e]:f.userElo.tags[e]?.score??u[e];y[e]={before:u[e],after:n,score:t}}let b={cardId:n,at:h,userScore:_,global:{before:r,after:f.userElo.global.score},card:{before:c,after:e?f.cardElo.global.score:c},...l.length?{tags:y}:{}};e||x.info(`[EloService] QA account: card ELO for ${n} not written`);let S=await Promise.allSettled([this.user.updateUserElo(t,f.userElo),e?a.updateCardElo(n,f.cardElo):Promise.resolve(null)]),C=S[0].status===`fulfilled`,w=S[1].status===`fulfilled`;if(C&&w){let e=S[0].value,t=S[1].value;if(e.ok&&t&&t.ok){let e=Object.keys(g).length-1;x.info(`[EloService] Updated ELOS (per-tag, ${e} tags):
51
+ \tUser: ${JSON.stringify(f.userElo)})
52
+ \tCard: ${JSON.stringify(f.cardElo)})
53
+ `)}}else x.warn(`[EloService] Partial ELO update (per-tag):
54
+ \tUser ELO update: ${C?`SUCCESS`:`FAILED`}
55
+ \tCard ELO update: ${w?`SUCCESS`:`FAILED`}`),!C&&S[0].status===`rejected`&&x.error(`[EloService] User ELO update error:`,S[0].reason),!w&&S[1].status===`rejected`&&x.error(`[EloService] Card ELO update error:`,S[1].reason);return b}return null}},ResponseProcessor=class{constructor(e,t,n){u(this,`srsService`,void 0),u(this,`eloService`,void 0),u(this,`onEloEvent`,void 0),this.srsService=e,this.eloService=t,this.onEloEvent=n}logEloFailure(e,t){return n=>x.error(`[ResponseProcessor] ELO update failed (${e}) for ${t}:`,n)}trackElo(e,t,n){e.then(e=>{e&&this.onEloEvent?.(e)}).catch(this.logEloFailure(t,n))}parsePerformance(e){return typeof e==`number`?{globalScore:e,taggedPerformance:null}:a(e)?{globalScore:e._global,taggedPerformance:e}:(x.warn(`[ResponseProcessor] Unexpected performance structure, using neutral score`,{performance:e}),{globalScore:.5,taggedPerformance:null})}async processResponse(e,t,n,i,a,o,s,c,l,u){if(!r(e))return{nextCardAction:`dismiss-success`,shouldLoadNextCard:!0,isCorrect:!0,shouldClearFeedbackShadow:!0};try{let r=await t,d;return d=e.isCorrect?this.processCorrectResponse(e,r,n,i,a,o,s,l,u):this.processIncorrectResponse(e,r,i,a,o,s,c,l,u),e.deferAdvance&&d.shouldLoadNextCard&&(x.info(`[ResponseProcessor] deferAdvance requested — suppressing navigation, action stashed:`,{nextCardAction:d.nextCardAction}),d={...d,shouldLoadNextCard:!1,deferred:!0}),d}catch(e){throw x.error(`[ResponseProcessor] Failed to load card history`,{e,cardId:s}),e}}processCorrectResponse(e,t,n,r,i,a,o,s,c){if(e.priorAttemps===0){i.card.tags.includes(`srs:skip`)||this.srsService.scheduleReview(t,n);let{globalScore:s,taggedPerformance:c}=this.parsePerformance(e.performance);if(c){let n=Object.keys(c).filter(e=>e!==`_global`),s=n.filter(e=>c[e]===null),l=n.filter(e=>c[e]!==null);x.info(`[FirstContactElo] correct first-attempt per-tag ELO update for ${o} (historyLen=${t.records.length}, priorAttemps=${e.priorAttemps}): scored=[${l.join(`, `)}] count-only=[${s.join(`, `)}]`),this.trackElo(this.eloService.updateUserAndCardEloPerTag(c,a,o,r,i),`correct per-tag`,o)}else{let n=.5+s/2;if(t.records.length===1)this.trackElo(this.eloService.updateUserAndCardElo(n,a,o,r,i),`correct`,o);else{let e=Math.ceil(32/t.records.length);this.trackElo(this.eloService.updateUserAndCardElo(n,a,o,r,i,e),`correct repeat-view`,o)}x.info(`[FirstContactElo] correct first-attempt ELO update (score=${n.toFixed(3)}) for ${o} (historyLen=${t.records.length}, priorAttemps=${e.priorAttemps})`)}return{nextCardAction:`dismiss-success`,shouldLoadNextCard:!0,isCorrect:!0,performanceScore:s,shouldClearFeedbackShadow:!0}}else{let t=c>=s;x.info(`[ResponseProcessor] Processed correct response (retry attempt - no scheduling/ELO); sessionViews=${c}/${s} -> ${t?`dismiss-success`:`marked-failed`}`);let{globalScore:n}=this.parsePerformance(e.performance);return{nextCardAction:t?`dismiss-success`:`marked-failed`,shouldLoadNextCard:!0,isCorrect:!0,performanceScore:n,shouldClearFeedbackShadow:!0}}}processIncorrectResponse(e,t,n,r,i,a,o,s,c){let{taggedPerformance:l}=this.parsePerformance(e.performance),u=!1;return e.priorAttemps===0?(l?(this.trackElo(this.eloService.updateUserAndCardEloPerTag(l,i,a,n,r),`incorrect per-tag`,a),x.info(`[FirstContactElo] incorrect first-attempt per-tag ELO update for ${a} (historyLen=${t.records.length}, priorAttemps=${e.priorAttemps}, tags=${Object.keys(l).length-1})`)):(this.trackElo(this.eloService.updateUserAndCardElo(0,i,a,n,r),`incorrect`,a),x.info(`[FirstContactElo] incorrect first-attempt ELO update (score=0) for ${a} (historyLen=${t.records.length}, priorAttemps=${e.priorAttemps})`)),u=!0):x.info(`[FirstContactElo] incorrect retry — no ELO update for ${a} (historyLen=${t.records.length}, priorAttemps=${e.priorAttemps})`),r.records.length>=o?c>=s?(u?x.info(`[FirstContactElo] dismiss-failed — ELO already updated this response, skipping double penalty for ${a}`):(l?this.trackElo(this.eloService.updateUserAndCardEloPerTag(l,i,a,n,r),`dismiss-failed per-tag`,a):this.trackElo(this.eloService.updateUserAndCardElo(0,i,a,n,r),`dismiss-failed`,a),x.info(`[FirstContactElo] dismiss-failed final ELO penalty for ${a} (historyLen=${t.records.length}, sessionViews=${c})`)),{nextCardAction:`dismiss-failed`,shouldLoadNextCard:!0,isCorrect:!1,shouldClearFeedbackShadow:!0}):{nextCardAction:`marked-failed`,shouldLoadNextCard:!0,isCorrect:!1,shouldClearFeedbackShadow:!0}:{nextCardAction:`none`,shouldLoadNextCard:!1,isCorrect:!1,shouldClearFeedbackShadow:!0}}};function parseAudioURIs(e){return typeof e==`string`?e.match(/https?:\/\/[^\s"'<>]+\.(wav|mp3|ogg|m4a|aac|webm)/gi)??[]:[]}function prefetchAudio(e){return new Promise(t=>{let n=new Audio;n.preload=`auto`;let cleanup=()=>{n.oncanplaythrough=null,n.onerror=null};n.oncanplaythrough=()=>{cleanup(),t()},n.onerror=()=>{cleanup(),x.warn(`[CardHydrationService] Failed to prefetch audio: ${e}`),t()},n.src=e})}var CardHydrationService=class{constructor(e,t,n){u(this,`hydratedCards`,new Map),u(this,`hydrationInFlight`,new Set),u(this,`hydrationInProgress`,!1),this.getViewComponent=e,this.getCourseDB=t,this.getItemsToHydrate=n}getHydratedCard(e){return this.hydratedCards.get(e)??null}hasHydratedCard(e){return this.hydratedCards.has(e)}removeCard(e){this.hydratedCards.delete(e)}async ensureHydratedCards(){this.fillHydratedCards()}async waitForCard(e){if(this.hydratedCards.has(e))return this.hydratedCards.get(e);this.hydrationInProgress||this.fillHydratedCards();let t=0;for(;t<1e4;){if(this.hydratedCards.has(e))return this.hydratedCards.get(e);if(!this.hydrationInFlight.has(e)&&!this.hydrationInProgress)break;await new Promise(e=>setTimeout(e,25)),t+=25}return this.hydratedCards.get(e)??null}get hydratedCount(){return this.hydratedCards.size}getHydratedCardIds(){return Array.from(this.hydratedCards.keys())}async fillHydratedCards(){if(!this.hydrationInProgress){this.hydrationInProgress=!0;try{let e=this.getItemsToHydrate();for(let t of e)if(!(this.hydratedCards.has(t.cardID)||this.hydrationInFlight.has(t.cardID)))try{await this.hydrateCard(t)}catch(e){x.error(`[CardHydrationService] Error hydrating card ${t.cardID}:`,e)}}finally{this.hydrationInProgress=!1}}}async hydrateCard(e){if(!(this.hydratedCards.has(e.cardID)||this.hydrationInFlight.has(e.cardID))){this.hydrationInFlight.add(e.cardID);try{let t=this.getCourseDB(e.courseID),[n,r]=await Promise.all([t.getCourseDoc(e.cardID),t.getAppliedTagsBatch([e.cardID])]);d(n.elo)||(n.elo=h(n.elo));let i=this.getViewComponent(n.id_view),a=await Promise.all(n.id_displayable_data.map(e=>t.getCourseDoc(e,{attachments:!0,binary:!0}))),o=[];a.forEach(e=>{e.data.forEach(e=>{o.push(...parseAudioURIs(e.data))})});let s=[...new Set(o)];s.length>0&&(x.debug(`[CardHydrationService] Prefetching ${s.length} audio files for card ${e.cardID}`),await Promise.allSettled(s.map(prefetchAudio)));let c=a.map(displayableDataToViewData).reverse();this.hydratedCards.set(e.cardID,{item:{...e,elo:h(n.elo).global.score},view:i,data:c,tags:r.get(e.cardID)??[]}),x.debug(`[CardHydrationService] Hydrated card ${e.cardID}`)}finally{this.hydrationInFlight.delete(e.cardID)}}}},ItemQueue=class{constructor(){u(this,`q`,[]),u(this,`seenCardIds`,[]),u(this,`_dequeueCount`,0)}get dequeueCount(){return this._dequeueCount}add(e,t){this.seenCardIds.find(e=>e===t)||(this.seenCardIds.push(t),this.q.push(e))}addAll(e,t){e.forEach(e=>this.add(e,t(e)))}get length(){return this.q.length}peek(e){return this.q[e]}dequeue(e){if(this.q.length!==0){this._dequeueCount++;let t=this.q.splice(0,1)[0];if(e){let n=e(t),r=this.seenCardIds.indexOf(n);r>-1&&this.seenCardIds.splice(r,1)}return t}else return null}replaceAll(e,t){this.q=[],this.seenCardIds=[];for(let n of e){let e=t(n);this.seenCardIds.includes(e)||(this.seenCardIds.push(e),this.q.push(n))}}mergeToFront(e,t,n){let r=0,i=[];for(let a of e){let e=t(a);if(!this.seenCardIds.includes(e))this.seenCardIds.push(e),i.push(a),r++;else if(n?.has(e)){let n=this.q.findIndex(n=>t(n)===e);n>=0&&i.push(...this.q.splice(n,1))}}return this.q.unshift(...i),r}get toString(){return`${typeof this.q[0]}:\n`+this.q.map(e=>`\t${e.courseID}+${e.cardID}: ${e.status}`).join(`
56
+ `)}},q,J=5;function sig4(e){return Number(e.toPrecision(4))}function toRunCard(e){return{cardId:e.cardId,origin:e.origin,...e.generator?{generator:e.generator}:{},...e.required?{required:e.required}:{},score:Number.isFinite(e.finalScore)?sig4(e.finalScore):null,selected:e.selected}}function toRunCardTrail(e){return{...toRunCard(e),trail:e.provenance.filter(e=>e.action!==`passed`).map(e=>({strategyName:e.strategyName,action:e.action,score:sig4(e.score),reason:e.reason}))}}function persistedReading(e){return{...e,urgency:sig4(e.urgency),multiplier:sig4(e.multiplier),inputs:Object.fromEntries(Object.entries(e.inputs).map(([e,t])=>[e,sig4(t)]))}}function persistedRunCards(e){let t=e.cards.filter(e=>e.selected),n=e.cards.filter(e=>!e.selected).slice(0,J);return[...t,...n].map(toRunCard)}function persistedUnselectedNew(e){return{...e.nextInLine?{nextInLine:toRunCardTrail(e.nextInLine)}:{},...e.topGenerated?{topGenerated:toRunCardTrail(e.topGenerated)}:{}}}var Y=(q=class SessionController extends s{set sessionRecord(e){this._sessionRecord=e}get secondsRemaining(){return this._secondsRemaining}get hasCardGuarantee(){return this._minCardsGuarantee>0}get report(){let e=this.supplyQ.dequeueCount;return`${e} supply ${e===1?`card`:`cards`} drawn`}get detailedReport(){return this.supplyQ.toString+`
57
+ `+this.failedQ.toString}constructor(e,t,n,r,i,a){super(),u(this,`_className`,`SessionController`),u(this,`services`,void 0),u(this,`srsService`,void 0),u(this,`eloService`,void 0),u(this,`hydrationService`,void 0),u(this,`mixer`,void 0),u(this,`dataLayer`,void 0),u(this,`courseNameCache`,new Map),u(this,`_defaultBatchLimit`,20),u(this,`sources`,void 0),u(this,`_sessionRecord`,[]),u(this,`_currentCard`,null),u(this,`supplyQ`,new ItemQueue),u(this,`failedQ`,new ItemQueue),u(this,`_supplyDrawsSinceFailed`,0),u(this,`_replanPromise`,null),u(this,`_activeReplanLabel`,null),u(this,`_wellIndicatedRemaining`,0),u(this,`_suppressQualityReplan`,!1),u(this,`_minCardsGuarantee`,0),u(this,`_sessionHints`,null),u(this,`_servedCardIds`,new Set),u(this,`_outcomeObservers`,[]),u(this,`_sessionControls`,null),u(this,`sessionId`,void 0),u(this,`_courseId`,void 0),u(this,`_stateSnapshotProvider`,void 0),u(this,`_sessionDoc`,null),u(this,`_openDocPromise`,null),u(this,`_runLog`,[]),u(this,`_eloLog`,[]),u(this,`_sessionClosed`,!1),u(this,`startTime`,void 0),u(this,`endTime`,void 0),u(this,`_secondsRemaining`,void 0),u(this,`_intervalHandle`,void 0),this.sessionId=newSessionId(),y(this.sessionId),this.dataLayer=n,this.mixer=i||new QuotaRoundRobinMixer,this.srsService=new SrsService(n.getUserDB()),this.eloService=new EloService(n,n.getUserDB()),this.hydrationService=new CardHydrationService(r,e=>n.getCourseDB(e),()=>this._getItemsToHydrate()),this.services={response:new ResponseProcessor(this.srsService,this.eloService,e=>this._recordEloEvent(e))},this.sources=e,this.startTime=new Date,this._secondsRemaining=t,this.endTime=new Date(this.startTime.valueOf()+1e3*this._secondsRemaining),a?.defaultBatchLimit!==void 0&&(this._defaultBatchLimit=a.defaultBatchLimit),a?.outcomeObservers?.length&&(this._outcomeObservers=[...a.outcomeObservers]),this._courseId=a?.courseId,this._stateSnapshotProvider=a?.stateSnapshotProvider,this.log(`Session constructed:
58
+ sessionId: ${this.sessionId}
59
+ startTime: ${this.startTime}
60
+ endTime: ${this.endTime}
61
+ defaultBatchLimit: ${this._defaultBatchLimit}`),registerActiveController(this)}tick(){this._secondsRemaining=Math.floor((this.endTime.valueOf()-Date.now())/1e3),this._secondsRemaining<=0&&clearInterval(this._intervalHandle)}estimateCleanupTime(){let e=0;for(let t=0;t<this.failedQ.length;t++){let n=this.failedQ.peek(t),r=this._sessionRecord.find(e=>e.item.cardID===n.cardID),i=0;if(r){for(let e=0;e<r.records.length;e++)i+=r.records[e].timeSpent;i/=r.records.length,e+=i}}let t=e/1e3;return this.log(`Failed card cleanup estimate: ${Math.round(t)}`),t}async prepareSession(){if(this.sources.some(e=>typeof e.getWeightedCards!=`function`))throw Error(`[SessionController] All content sources must implement getWeightedCards().`);clearStaleSessionDebugState();let e=await this.getWeightedContent();this._recordRuns(`bootstrap`),this._wellIndicatedRemaining=e,e>=0&&e<SessionController.MIN_WELL_INDICATED&&this.log(`[Init] Only ${e}/${SessionController.MIN_WELL_INDICATED} well-indicated cards in initial load`),await this.hydrationService.ensureHydratedCards(),startSessionTracking(this.sessionId,this.supplyQ.length,this.failedQ.length),this._openDocPromise=this._openSessionDoc(),this._intervalHandle=setInterval(()=>{this.tick()},1e3)}_recordRuns(e,t){for(let n of b()){if(this._runLog.length>=SessionController.MAX_LOGGED_RUNS)break;this._runLog.push({runId:n.runId,at:n.timestamp.toISOString(),label:e,...t?{mode:t}:{},generatedCount:n.generatedCount,finalCount:n.finalCount,reviewsSelected:n.reviewsSelected,newSelected:n.newSelected,...typeof n.userElo==`number`?{userElo:n.userElo}:{},...n.generators?{generators:n.generators}:{},...n.filters?{filters:n.filters}:{},...n.hints?{hints:n.hints}:{},...n.discardedTail?{discardedTail:n.discardedTail}:{},cards:persistedRunCards(n),...n.unselectedNew?{unselectedNew:persistedUnselectedNew(n.unselectedNew)}:{},...n.regulators?{regulators:n.regulators.map(persistedReading)}:{},...n.versions?{versions:n.versions}:{}})}}async _captureState(e){if(this._stateSnapshotProvider)try{return await Promise.race([Promise.resolve(this._stateSnapshotProvider(e)),new Promise(e=>setTimeout(()=>e(void 0),3e3))])}catch(t){this.log(`[Session] state snapshot (${e}) failed: ${t}`);return}}async _openSessionDoc(){if(this._courseId)try{let e=this.dataLayer.getUserDB(),t={_id:makeStudySessionId(this._courseId,e.getUsername(),this.sessionId),docType:E.STUDY_SESSION,sessionId:this.sessionId,courseId:this._courseId,userId:e.getUsername(),startTime:this.startTime.toISOString(),status:`open`,plannedSeconds:Math.round((this.endTime.valueOf()-this.startTime.valueOf())/1e3),config:{defaultBatchLimit:this._defaultBatchLimit,sourceCount:this.sources.length,initHints:this._sessionHints},versions:T(),initialQueues:{supplyQ:this.supplyQ.length,failedQ:this.failedQ.length},runs:[...this._runLog],stateAtStart:await this._captureState(`start`)};this._sessionDoc=t,await e.putStudySession(t),this.log(`[Session] Opened session record ${t._id}`)}catch(e){x.warn(`[SessionController] Failed to open session record: ${e}`)}}async requestReplan(e){let t=this.normalizeReplanOptions(e),n=this._replanHasIntent(t);if(this._replanPromise){if(!n)return this.log(`Replan already in progress, coalescing unhinted auto-replan`),this._replanPromise;let e=t.label?` [${t.label}]`:``;this.log(`Replan in progress; queueing hint-bearing replan${e} behind in-flight run`);let r=this._replanPromise.catch(()=>void 0).then(()=>this._runReplan(t)),i=r.finally(()=>{this._replanPromise===i&&(this._replanPromise=null,this._activeReplanLabel=null)});return this._replanPromise=i,r}let r=this._runReplan(t),i=r.finally(()=>{this._replanPromise===i&&(this._replanPromise=null,this._activeReplanLabel=null)});this._replanPromise=i,await r}_replanHasIntent(e){return!!(e.limit!==void 0||e.minFollowUpCards!==void 0||e.mode&&e.mode!==`replace`||e.hints&&Object.keys(e.hints).length>0||e.sessionHints!==void 0||e.mergeSessionHints!==void 0)}async _runReplan(e){this._activeReplanLabel=e.label??`(auto)`,e.hints||(e.hints={});let n=e.hints,r=new Set(n.excludeCards??[]);this._currentCard?.item.cardID&&r.add(this._currentCard.item.cardID);for(let e of this._sessionRecord)r.add(e.card.card_id);this.supplyQ.length>0&&r.add(this.supplyQ.peek(0).cardID),n.excludeCards=[...r],e.sessionHints!==void 0&&(this._sessionHints=e.sessionHints,this.log(`[Replan] Session hints ${e.sessionHints?`set`:`cleared`}: ${JSON.stringify(e.sessionHints)}`)),e.mergeSessionHints!==void 0&&(this._sessionHints=t([this._sessionHints,e.mergeSessionHints])??null,this.log(`[Replan] Session hints merged: ${JSON.stringify(this._sessionHints)}`)),this._applyHintsToSources(e.hints,e.label);let i=e.label?` [${e.label}]`:``;this.log(`Mid-session replan requested${i} (limit: ${e.limit??`default`}, mode: ${e.mode??`replace`}${e.hints?`, with hints`:``})`),e.minFollowUpCards!==void 0&&e.minFollowUpCards>0&&(this._minCardsGuarantee=Math.max(this._minCardsGuarantee,e.minFollowUpCards),this.log(`[Replan] Card guarantee set to ${this._minCardsGuarantee}`)),await this._executeReplan(e)}setSessionHints(e){this._sessionHints=e,this.log(`Session hints ${e?`set`:`cleared`}: ${JSON.stringify(e)}`)}getSessionHints(){return this._sessionHints}getDebugSnapshot(){let describe=e=>{let t=[];for(let n=0;n<e.length;n++){let r=e.peek(n);t.push({cardID:r.cardID,status:r.status,origin:c(r)?`review`:`new`,score:r.score})}return{length:e.length,dequeueCount:e.dequeueCount,cards:t}},e=this._sessionRecord.map(e=>{let t=e.records[e.records.length-1];return{cardID:e.item.cardID,status:e.item.status,attempts:e.records.length,correct:t&&r(t)?t.isCorrect:null,timeSpentMs:e.records.reduce((e,t)=>e+t.timeSpent,0)}});return{sessionId:this.sessionId,secondsRemaining:this.secondsRemaining,hasCardGuarantee:this.hasCardGuarantee,minCardsGuarantee:this._minCardsGuarantee,wellIndicatedRemaining:this._wellIndicatedRemaining,currentCard:this._currentCard?.item.cardID??null,sessionHints:this._sessionHints,replanActive:this._replanPromise!==null,replanLabel:this._activeReplanLabel,supplyQ:describe(this.supplyQ),failedQ:describe(this.failedQ),reviewBacklog:_(),strategyPressure:w(),drawnCards:e}}mergeSessionHints(e){this._sessionHints=t([this._sessionHints,e])??null,this.log(`Session hints merged: ${JSON.stringify(this._sessionHints)}`)}_applyHintsToSources(e,n){let r=e&&n?{...e,_label:n}:e,i=t([this._sessionHints,r]);if(i)for(let e of this.sources)e.setEphemeralHints?.(i)}_getSessionControls(){return this._sessionControls||(this._sessionControls={getSessionHints:()=>this.getSessionHints(),setSessionHints:e=>this.setSessionHints(e),mergeSessionHints:e=>this.mergeSessionHints(e),requestReplan:e=>this.requestReplan(e)}),this._sessionControls}_recordEloEvent(e){this._eloLog.length>=SessionController.MAX_LOGGED_ELO_EVENTS||this._eloLog.push(e)}async _notifyOutcomeObservers(e,t,n){if(this._outcomeObservers.length===0||!r(e))return;let i={record:e,card:t.card,result:n},a=this._getSessionControls();for(let e of this._outcomeObservers)try{await e(i,a)}catch(e){this.error(`[OutcomeObserver] observer threw; ignoring`,e)}}async _replanUncoalesced(e){let t=this._runReplan(e),n=t.finally(()=>{this._replanPromise===n&&(this._replanPromise=null,this._activeReplanLabel=null)});this._replanPromise=n,await t}normalizeReplanOptions(e){if(!e)return{};let t=[`hints`,`sessionHints`,`limit`,`mode`,`label`,`minFollowUpCards`];return Object.keys(e).some(e=>t.includes(e))?e:{hints:e}}async _executeReplan(e={}){let t=e.limit,n=e.mode??`replace`,r=await this.getWeightedContent({replan:!0,additive:n===`merge`,limit:t});this._recordRuns(e.label??`(auto)`,n),this._wellIndicatedRemaining=r,t!==void 0&&t<this._defaultBatchLimit?(this._suppressQualityReplan=!0,this.log(`[Replan] Burst mode (limit=${t}): suppressing quality-based auto-replan`)):this._suppressQualityReplan=!1,r>=0&&r<SessionController.MIN_WELL_INDICATED&&this.log(`[Replan] Only ${r}/${SessionController.MIN_WELL_INDICATED} well-indicated cards after replan`),await this.hydrationService.ensureHydratedCards();let i=e.label?` [${e.label}]`:``;this.log(`Replan complete${i}: supplyQ now has ${this.supplyQ.length} cards (mode=${n})`),snapshotQueues(this.supplyQ.length,this.failedQ.length)}addTime(e){this.endTime=new Date(this.endTime.valueOf()+1e3*e)}get failedCount(){return this.failedQ.length}toString(){return`Session: ${this.supplyQ.length} supply, ${this.failedQ.length} failed`}reportString(){return`${this.supplyQ.dequeueCount} supply, ${this.failedQ.dequeueCount} failed`}getDebugInfo(){let e=this.sources.some(e=>typeof e.getWeightedCards==`function`),extractQueueItems=(e,t=10)=>{let n=[];for(let r=0;r<Math.min(e.length,t);r++){let t=e.peek(r);n.push({courseID:t.courseID||`unknown`,cardID:t.cardID||`unknown`,status:t.status||`unknown`,score:t.score})}return n};return{api:{mode:e?`weighted`:`legacy`,description:e?`Using getWeightedCards() API with scored candidates`:`ERROR: getWeightedCards() not a function.`},supplyQueue:{length:this.supplyQ.length,dequeueCount:this.supplyQ.dequeueCount,items:extractQueueItems(this.supplyQ)},failedQueue:{length:this.failedQ.length,dequeueCount:this.failedQ.dequeueCount,items:extractQueueItems(this.failedQ)},hydratedCache:{count:this.hydrationService.hydratedCount,cardIds:this.hydrationService.getHydratedCardIds()},replan:{inProgress:this._replanPromise!==null,suppressQualityReplan:this._suppressQualityReplan,defaultBatchLimit:this._defaultBatchLimit,minCardsGuarantee:this._minCardsGuarantee}}}async getWeightedContent(e){let t=e?.replan??!1,n=e?.additive??!1,r=e?.limit??this._defaultBatchLimit,i=r;t||this._applyHintsToSources();let a=[];for(let e=0;e<this.sources.length;e++){let n=this.sources[e];try{let t=(await n.getWeightedCards(i)).cards;a.push({sourceIndex:e,weighted:t})}catch(n){if(this.error(`Failed to get content from source ${e}:`,n),this.sources.length===1&&!t)throw Error(`Cannot start session: failed to load content from source ${e}`)}}if(a.length===0){if(t)return this.log(`Replan: no content from any source, keeping existing supplyQ`),-1;throw Error(`Cannot start session: failed to load content from all ${this.sources.length} source(s). Check logs for details.`)}let o=this.mixer.mix(a,i*this.sources.length),s=a.map(e=>e.weighted[0]?.courseId||`source-${e.sourceIndex}`);await Promise.all(s.map(async e=>{if(!this.courseNameCache.has(e))try{let t=await this.dataLayer.getCoursesDB().getCourseConfig(e);this.courseNameCache.set(e,t.name)}catch{}}));let c=s.map(e=>this.courseNameCache.get(e)),l=this.mixer instanceof QuotaRoundRobinMixer?Math.ceil(i*this.sources.length/a.length):void 0;captureMixerRun(this.mixer.constructor.name,a,s,c,i*this.sources.length,l,o);let u=o.filter(e=>!this._servedCardIds.has(e.cardId)),d=u.filter(e=>e.score===1/0),f=u.filter(e=>e.score!==1/0),p=[...d,...f.slice(0,Math.max(0,r-d.length))],m=new Set(d.map(e=>e.cardId)),h=p.filter(e=>e.score>=SessionController.WELL_INDICATED_SCORE).length,g=t?`Replan content:
62
+ `:`Mixed content session created with:
63
+ `,_=p.map(e=>{let t=S(e),n=Number.isFinite(e.score)?e.score.toFixed(2):`+INF`;return g+=`${t===`review`?`Review`:`New`}: ${e.courseId}::${e.cardId} (score: ${n})\n`,this._buildSupplyItem(e,t)});if(n){let e=this.supplyQ.mergeToFront(_,e=>e.cardID,m);g+=`Additive merge: ${e} cards added to front of supplyQ\n`}else if(t)this.supplyQ.replaceAll(_,e=>e.cardID);else for(let e of _)this.supplyQ.add(e,e.cardID);return this.log(g),h}_buildSupplyItem(e,t=S(e)){let n={cardID:e.cardId,courseID:e.courseId,contentSourceType:`course`,contentSourceID:e.courseId,score:e.score};return t===`review`?{...n,status:`review`,reviewID:e.reviewID}:{...n,status:`new`}}_getItemsToHydrate(){let e=[];for(let t=0;t<Math.min(3,this.supplyQ.length);t++)e.push(this.supplyQ.peek(t));for(let t=0;t<Math.min(2,this.failedQ.length);t++)e.push(this.failedQ.peek(t));return e}_selectNextItemToHydrate(){if(this.supplyQ.length===0&&this.failedQ.length===0||this._secondsRemaining<2&&this.failedQ.length===0&&this._minCardsGuarantee<=0)return null;if(this._secondsRemaining<=0&&this._minCardsGuarantee<=0)return this.failedQ.length>0?this.failedQ.peek(0):null;let e=this.supplyQ.length>0?this.supplyQ.peek(0):null;return this._minCardsGuarantee>0&&e?e:this.failedQ.length>0&&this._shouldInterleaveFailed(e!==null)?this.failedQ.peek(0):e||(this.failedQ.length>0?this.failedQ.peek(0):(this.log(`No more cards available for the session!`),null))}_shouldInterleaveFailed(e){return this.failedQ.length===0?!1:!e||this._secondsRemaining-this.estimateCleanupTime()<=SessionController.FAILED_ENDGAME_SLACK_SECONDS?!0:this._supplyDrawsSinceFailed>=SessionController.FAILED_INTERLEAVE_EVERY}async nextCard(e=`dismiss-success`){if(this.dismissCurrentCard(e),this._minCardsGuarantee>0&&(this._minCardsGuarantee--,this.log(`[CardGuarantee] ${this._minCardsGuarantee} guaranteed cards remaining`)),this._replanPromise&&this.supplyQ.length===0&&this.failedQ.length===0&&(this.log(`nextCard: queues empty, awaiting in-flight replan before drawing`),await this._replanPromise),this.supplyQ.length<=SessionController.DEPLETION_PREFETCH_THRESHOLD&&this._secondsRemaining>0&&!this._replanPromise&&(this._suppressQualityReplan=!1,this.log(`[AutoReplan:depletion] supplyQ has ${this.supplyQ.length} card(s) (${this.failedQ.length} failed pending) with ${this._secondsRemaining}s remaining. Triggering background replan.`),this.requestReplan({label:`auto:depletion`,mode:`merge`})),!this._suppressQualityReplan&&this._wellIndicatedRemaining<=3&&this.supplyQ.length>0&&!this._replanPromise&&(this.log(`[AutoReplan:quality] ${this._wellIndicatedRemaining} well-indicated cards remaining (supplyQ: ${this.supplyQ.length}). Triggering background replan.`),this.requestReplan({label:`auto:quality`})),this._secondsRemaining<=0&&this.failedQ.length===0&&this._minCardsGuarantee<=0)return this._currentCard=null,endSessionTracking(),this._terminate(),null;let t=0;for(;this._secondsRemaining>0&&this.supplyQ.length===0&&this.failedQ.length===0;)if(this.log(`[WedgeBreaker] All queues empty with ${this._secondsRemaining}s remaining. Running pipeline (attempt ${t+1}/3).`),await this._replanUncoalesced({label:`wedge-breaker`}),this.supplyQ.length===0&&this.failedQ.length===0){if(t++,t>=3){this.log(`[WedgeBreaker] Pipeline returned no content 3 consecutive times. Giving up; session will end.`);break}await new Promise(e=>setTimeout(e,250))}else t=0;for(let e=0;e<20;e++){let e=this._selectNextItemToHydrate();if(!e)return this._currentCard=null,endSessionTracking(),this._terminate(),null;let t=this.hydrationService.getHydratedCard(e.cardID);if(t||(t=await this.hydrationService.waitForCard(e.cardID)),this.removeItemFromQueue(e),t){await this.hydrationService.ensureHydratedCards(),this._currentCard=t;let n=e.status===`review`||e.status===`failed-review`?`review`:e.status===`new`||e.status===`failed-new`?`new`:`failed`,r=e.status.startsWith(`failed`)?`failedQ`:`supplyQ`;recordCardPresentation(e.cardID,e.courseID,this.courseNameCache.get(e.courseID),n,r,e.score);for(let t of this.sources)t.notePresented?.({cardId:e.cardID,courseId:e.courseID,status:e.status});return snapshotQueues(this.supplyQ.length,this.failedQ.length),t}this.log(`Skipping card ${e.cardID}: hydration failed, trying next`),c(e)&&this.srsService.removeReview(e.reviewID)}return this.log(`Exhausted 20 skip attempts finding a hydratable card`),this._currentCard=null,endSessionTracking(),this._terminate(),null}_terminate(){this.endSession().catch(e=>{x.warn(`[SessionController] endSession failed: ${e}`)})}async submitResponse(e,t,n,r,i,a,o,s,c){let l={...r.item},u=await this.services.response.processResponse(e,t,l,n,r,i,a,o,s,c);return await this._notifyOutcomeObservers(e,r,u),u}dismissCurrentCard(e=`dismiss-success`){if(this._currentCard)if(e===`dismiss-success`)this.hydrationService.removeCard(this._currentCard.item.cardID);else if(e===`marked-failed`){let e;e=c(this._currentCard.item)?{cardID:this._currentCard.item.cardID,courseID:this._currentCard.item.courseID,contentSourceID:this._currentCard.item.contentSourceID,contentSourceType:this._currentCard.item.contentSourceType,status:`failed-review`,reviewID:this._currentCard.item.reviewID}:{cardID:this._currentCard.item.cardID,courseID:this._currentCard.item.courseID,contentSourceID:this._currentCard.item.contentSourceID,contentSourceType:this._currentCard.item.contentSourceType,status:`failed-new`},this.failedQ.add(e,e.cardID),this._supplyDrawsSinceFailed=0}else (e===`dismiss-error`||e===`dismiss-failed`)&&this.hydrationService.removeCard(this._currentCard.item.cardID)}removeItemFromQueue(e){this._clearDurableRequirement(e.cardID),this._servedCardIds.add(e.cardID),this.failedQ.peek(0)?.cardID===e.cardID?(this.failedQ.dequeue(e=>e.cardID),this._supplyDrawsSinceFailed=0):this.supplyQ.peek(0)?.cardID===e.cardID&&(this.supplyQ.dequeue(e=>e.cardID),this._supplyDrawsSinceFailed++,this._wellIndicatedRemaining>0&&this._wellIndicatedRemaining--)}_clearDurableRequirement(e){let t=this._sessionHints?.requireCards;if(!t||t.length===0)return;let n=t.filter(t=>t!==e);n.length!==t.length&&(this._sessionHints={...this._sessionHints,requireCards:n.length>0?n:void 0},this.log(`[Replan] Durable requirement satisfied & cleared on draw: ${e}`))}async endSession(e=`closed`){if(this._sessionClosed||(this._sessionClosed=!0,clearInterval(this._intervalHandle),y(void 0),await this._closeSessionDoc(e),!this._sessionRecord||this._sessionRecord.length===0))return;let t=this._sessionRecord.flatMap(e=>e.records).filter(e=>e.userAnswer!==void 0);if(t.length===0)return;let n=null,r=[];for(let e of this.sources)if(e.getOrchestrationContext){try{n=await e.getOrchestrationContext(),e.getStrategyIds&&r.push(...e.getStrategyIds())}catch(e){x.warn(`[SessionController] Failed to get orchestration context: ${e}`)}if(n)break}if(!n){x.debug(`[SessionController] No orchestration context available, skipping outcome recording`);return}let a=new Date().toISOString(),o=new Date(this.startTime).toISOString();await i(n,o,a,t,r)}async _closeSessionDoc(e){this._openDocPromise&&await this._openDocPromise;let t=this._sessionDoc;if(!t)return;let n=this._sessionRecord.flatMap(e=>e.records),i=n.filter(r);try{let r={...t,status:e,endTime:new Date().toISOString(),tally:{cardsPresented:this._sessionRecord.length,responses:n.length,correct:i.filter(e=>e.isCorrect).length,incorrect:i.filter(e=>!e.isCorrect).length,failedQRemaining:this.failedQ.length,secondsRemaining:Math.max(0,this._secondsRemaining)},runs:[...this._runLog],eloEvents:[...this._eloLog],finalHints:this._sessionHints,stateAtEnd:await this._captureState(`end`)};this._sessionDoc=r,await this.dataLayer.getUserDB().putStudySession(r),this.log(`[Session] Session record ${r._id} -> ${e} (${r.tally.cardsPresented} cards, ${r.tally.responses} responses, ${this._runLog.length} pipeline runs)`)}catch(e){x.warn(`[SessionController] Failed to close session record: ${e}`)}}},u(q,`MAX_LOGGED_RUNS`,100),u(q,`MAX_LOGGED_ELO_EVENTS`,2e3),u(q,`MIN_WELL_INDICATED`,5),u(q,`WELL_INDICATED_SCORE`,.1),u(q,`DEPLETION_PREFETCH_THRESHOLD`,3),u(q,`FAILED_INTERLEAVE_EVERY`,4),u(q,`FAILED_ENDGAME_SLACK_SECONDS`,20),q);async function importParsedCards(e,t,n){let r=[];for(let i of e)try{let e=await processCard(i,t,n);r.push(e)}catch(e){x.error(`Error processing card:`,e);let t=i.markdown;i.tags&&i.tags.length>0&&(t+=`\ntags: ${i.tags.join(`, `)}`),i.elo!==void 0&&(t+=`\nelo: ${i.elo}`),r.push({originalText:t,status:`error`,message:`Error processing card: ${e instanceof Error?e.message:`Unknown error`}`})}return r}async function processCard(e,t,n){let{markdown:r,tags:i,elo:a}=e,s=r;i.length>0&&(s+=`\ntags: ${i.join(`, `)}`),a!==void 0&&(s+=`\nelo: ${a}`);let c={Input:r,Uploads:[]},l={};for(let e of i)l[e]={score:a||0,count:1};try{let e=await t.addNote(n.courseCode,n.dataShape,c,n.userName,i,void 0,a?{global:{score:a,count:1},tags:l,misc:{}}:void 0);return e.status===o.ok?{originalText:s,status:`success`,message:`Card added successfully.`,cardId:e.id?e.id:`(unknown)`}:{originalText:s,status:`error`,message:e.message||`Failed to add card to database. Unknown error.`}}catch(e){return x.error(`Error adding note:`,e),{originalText:s,status:`error`,message:`Error adding card: ${e instanceof Error?e.message:`Unknown error`}`}}}function validateProcessorConfig(e){return e.dataShape?e.courseCode?e.userName?{isValid:!0}:{isValid:!1,errorMessage:`No user name provided for card processing`}:{isValid:!1,errorMessage:`No course code provided for card processing`}:{isValid:!1,errorMessage:`No data shape provided for card processing`}}export{QuotaRoundRobinMixer as _,endSessionTracking as a,displayableDataToViewData as b,K as c,getActiveController as d,registerActiveController as f,mountMixerDebugger as g,A as h,clearStaleSessionDebugState as i,snapshotQueues as l,captureMixerRun as m,validateProcessorConfig as n,mountSessionDebugger as o,toggleSessionOverlay as p,Y as r,recordCardPresentation as s,importParsedCards as t,startSessionTracking as u,makeStudySessionId as v,newSessionId as y};
64
+ //# sourceMappingURL=dist-Dp6eBE2S.js.map