@vue-skuilder/platform-ui 0.2.32 → 0.2.34

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 (124) hide show
  1. package/dist/assets/{About-B214b3Ir.js → About-sUaZ0Srj.js} +2 -2
  2. package/dist/assets/{About-B214b3Ir.js.map → About-sUaZ0Srj.js.map} +1 -1
  3. package/dist/assets/{AdminDashboard-CzTzSre6.js → AdminDashboard-cKNlDTB2.js} +2 -2
  4. package/dist/assets/{AdminDashboard-CzTzSre6.js.map → AdminDashboard-cKNlDTB2.js.map} +1 -1
  5. package/dist/assets/{AdminLearner-Bytn_WEj.js → AdminLearner-DXeevw2h.js} +2 -2
  6. package/dist/assets/{AdminLearner-Bytn_WEj.js.map → AdminLearner-DXeevw2h.js.map} +1 -1
  7. package/dist/assets/{ClassroomCtrlPanel-CNqwuP0s.js → ClassroomCtrlPanel-BeSz_WX4.js} +2 -2
  8. package/dist/assets/{ClassroomCtrlPanel-CNqwuP0s.js.map → ClassroomCtrlPanel-BeSz_WX4.js.map} +1 -1
  9. package/dist/assets/{Classrooms-CGj2OjuF.js → Classrooms-DTBqomQE.js} +3 -3
  10. package/dist/assets/{Classrooms-CGj2OjuF.js.map → Classrooms-DTBqomQE.js.map} +1 -1
  11. package/dist/assets/{CourseRouter-CfTN19pR.js → CourseRouter-CL8v2Zdk.js} +3 -3
  12. package/dist/assets/{CourseRouter-CfTN19pR.js.map → CourseRouter-CL8v2Zdk.js.map} +1 -1
  13. package/dist/assets/{CourseWare-BTFRjgBR-BJbHZcMM.js → CourseWare-BTFRjgBR-C3GJRVef.js} +3 -3
  14. package/dist/assets/{CourseWare-BTFRjgBR-BJbHZcMM.js.map → CourseWare-BTFRjgBR-C3GJRVef.js.map} +1 -1
  15. package/dist/assets/{Courses-CpGd_QfD.js → Courses-CUff-WLk.js} +3 -3
  16. package/dist/assets/{Courses-CpGd_QfD.js.map → Courses-CUff-WLk.js.map} +1 -1
  17. package/dist/assets/{EloModeration-BsqLd3Zv.js → EloModeration-6MUDz-Mu.js} +2 -2
  18. package/dist/assets/{EloModeration-BsqLd3Zv.js.map → EloModeration-6MUDz-Mu.js.map} +1 -1
  19. package/dist/assets/{JoinCode-DZIR9DQp.js → JoinCode-CW9Lk23D.js} +3 -3
  20. package/dist/assets/{JoinCode-DZIR9DQp.js.map → JoinCode-CW9Lk23D.js.map} +1 -1
  21. package/dist/assets/MarkdownRenderer-U_iPiA2x-DDruDu7E.js +53 -0
  22. package/dist/assets/MarkdownRenderer-U_iPiA2x-DDruDu7E.js.map +1 -0
  23. package/dist/assets/MarkdownRenderer-U_iPiA2x-VCa5mXh1.js +1 -0
  24. package/dist/assets/{NewCourseDialog-CBcivNiO.js → NewCourseDialog-CLm1rQyB.js} +2 -2
  25. package/dist/assets/{NewCourseDialog-CBcivNiO.js.map → NewCourseDialog-CLm1rQyB.js.map} +1 -1
  26. package/dist/assets/{ReleaseNotes-DT0-L42Z.js → ReleaseNotes-CmITE6hd.js} +2 -2
  27. package/dist/assets/{ReleaseNotes-DT0-L42Z.js.map → ReleaseNotes-CmITE6hd.js.map} +1 -1
  28. package/dist/assets/{RequestPasswordReset-B8k7NuRM.js → RequestPasswordReset-DPE6S2dU.js} +2 -2
  29. package/dist/assets/{RequestPasswordReset-B8k7NuRM.js.map → RequestPasswordReset-DPE6S2dU.js.map} +1 -1
  30. package/dist/assets/{ResetPassword-BZIUGR3j.js → ResetPassword-Dl6nj4jF.js} +2 -2
  31. package/dist/assets/{ResetPassword-BZIUGR3j.js.map → ResetPassword-Dl6nj4jF.js.map} +1 -1
  32. package/dist/assets/{Study-Cj7TcDn4.js → Study-Cf5yVLaY.js} +2 -2
  33. package/dist/assets/{Study-Cj7TcDn4.js.map → Study-Cf5yVLaY.js.map} +1 -1
  34. package/dist/assets/TagInformation-tqHJGkyw.js +2 -0
  35. package/dist/assets/{TagInformation-DibgRiob.js.map → TagInformation-tqHJGkyw.js.map} +1 -1
  36. package/dist/assets/{User-Np8Oiqyi.js → User-DCoA5JMB.js} +3 -3
  37. package/dist/assets/{User-Np8Oiqyi.js.map → User-DCoA5JMB.js.map} +1 -1
  38. package/dist/assets/UserStats-B25DZy-D.js +2 -0
  39. package/dist/assets/{UserStats-BMGNG7x3.js.map → UserStats-B25DZy-D.js.map} +1 -1
  40. package/dist/assets/{VerifyEmail-5HHoEaEd.js → VerifyEmail-DyWRQweA.js} +2 -2
  41. package/dist/assets/{VerifyEmail-5HHoEaEd.js.map → VerifyEmail-DyWRQweA.js.map} +1 -1
  42. package/dist/assets/admin-DCvFP6sY.js +4 -0
  43. package/dist/assets/{admin-C4Ua7x6R.js.map → admin-DCvFP6sY.js.map} +1 -1
  44. package/dist/assets/{chess-E2uOAyQS-CCtmF-5U.js → chess-E2uOAyQS-CP3XwSpG.js} +3 -3
  45. package/dist/assets/{chess-E2uOAyQS-CCtmF-5U.js.map → chess-E2uOAyQS-CP3XwSpG.js.map} +1 -1
  46. package/dist/assets/chess-Lfm7Fsvs-RoJ69a0B.js +1 -0
  47. package/dist/assets/common-ui.es-DHzI_ZVr.js +1 -0
  48. package/dist/assets/{common-ui.es-BNWvg8Db.js → common-ui.es-te1li8kU.js} +18 -18
  49. package/dist/assets/common-ui.es-te1li8kU.js.map +1 -0
  50. package/dist/assets/{dist-CIgUAYYy.js → dist-BnMJdH50.js} +14 -14
  51. package/dist/assets/dist-BnMJdH50.js.map +1 -0
  52. package/dist/assets/dist-CtnPlm6M.js +18 -0
  53. package/dist/assets/{dist-BIG2z9Yo.js.map → dist-CtnPlm6M.js.map} +1 -1
  54. package/dist/assets/dist-D4MdLcof.js +1 -0
  55. package/dist/assets/dist-Db-U8O3Z.js +1 -0
  56. package/dist/assets/{dist-otyR79at.js → dist-V9Xbab2f.js} +2 -2
  57. package/dist/assets/dist-V9Xbab2f.js.map +1 -0
  58. package/dist/assets/edit-ui.es-C7TI7NmB.js +36 -0
  59. package/dist/assets/edit-ui.es-C7TI7NmB.js.map +1 -0
  60. package/dist/assets/edit-ui.es-CiY2oEH8.js +1 -0
  61. package/dist/assets/{french-Dk7YG8Td-7f2kjsfA.js → french-Dk7YG8Td-Bfl4cirn.js} +2 -2
  62. package/dist/assets/{french-Dk7YG8Td-7f2kjsfA.js.map → french-Dk7YG8Td-Bfl4cirn.js.map} +1 -1
  63. package/dist/assets/french-evUMlbbq-DuW1vCaS.js +1 -0
  64. package/dist/assets/index-JRi1udkz.js +4 -0
  65. package/dist/assets/index-JRi1udkz.js.map +1 -0
  66. package/dist/assets/math-DR3fXDcX-BFIht0j2.js +1 -0
  67. package/dist/assets/math-D_8HiEQR-B9oNpF-3.js +34 -0
  68. package/dist/assets/math-D_8HiEQR-B9oNpF-3.js.map +1 -0
  69. package/dist/assets/piano-BN5Btq91-Jqe2eqme.js +1 -0
  70. package/dist/assets/piano-DF1g6yaX-CjD06Qz8.js +2 -0
  71. package/dist/assets/{piano-DF1g6yaX-CAYlAEmp.js.map → piano-DF1g6yaX-CjD06Qz8.js.map} +1 -1
  72. package/dist/assets/{pitch-CgGJFkZ1-C23Jvxwz.js → pitch-CgGJFkZ1-C-2hdk99.js} +2 -2
  73. package/dist/assets/{pitch-CgGJFkZ1-C23Jvxwz.js.map → pitch-CgGJFkZ1-C-2hdk99.js.map} +1 -1
  74. package/dist/assets/pitch-Dn0iNqiS-DpEcsscT.js +1 -0
  75. package/dist/assets/{server-B8QRdqwc.js → server-D4lhkoe2.js} +2 -2
  76. package/dist/assets/{server-B8QRdqwc.js.map → server-D4lhkoe2.js.map} +1 -1
  77. package/dist/assets/{sightsing-BFQ7HRig-DnGENSwZ.js → sightsing-BFQ7HRig-8K5qd7-K.js} +3 -3
  78. package/dist/assets/{sightsing-BFQ7HRig-DnGENSwZ.js.map → sightsing-BFQ7HRig-8K5qd7-K.js.map} +1 -1
  79. package/dist/assets/sightsing-CJX3k0Fd-CA3ntnlE.js +1 -0
  80. package/dist/assets/{typing-BevtfWlp-CyBXe67n.js → typing-BevtfWlp-BT263ZFw.js} +2 -2
  81. package/dist/assets/{typing-BevtfWlp-CyBXe67n.js.map → typing-BevtfWlp-BT263ZFw.js.map} +1 -1
  82. package/dist/assets/typing-k-ojjO7G-Bq4IfdFx.js +1 -0
  83. package/dist/assets/{vue-router-CDq4a4rc.js → vue-router-HoUBO3s7.js} +2 -2
  84. package/dist/assets/{vue-router-CDq4a4rc.js.map → vue-router-HoUBO3s7.js.map} +1 -1
  85. package/dist/assets/{vue.runtime.esm-bundler-C3q8JS9f.js → vue.runtime.esm-bundler--Fxmd6l9.js} +2 -2
  86. package/dist/assets/{vue.runtime.esm-bundler-C3q8JS9f.js.map → vue.runtime.esm-bundler--Fxmd6l9.js.map} +1 -1
  87. package/dist/assets/word-work-BOnRlZgd-BFwc1KBd.js +2 -0
  88. package/dist/assets/{word-work-BOnRlZgd-I_fnRmvE.js.map → word-work-BOnRlZgd-BFwc1KBd.js.map} +1 -1
  89. package/dist/assets/word-work-Dd6tIKrt-tFtMeyu1.js +1 -0
  90. package/dist/index.html +7 -7
  91. package/dist/sw.js +1 -1
  92. package/dist/sw.js.map +1 -1
  93. package/package.json +7 -7
  94. package/dist/assets/MarkdownRenderer-kStoDRNE-B0wYWYhQ.js +0 -1
  95. package/dist/assets/MarkdownRenderer-kStoDRNE-D6ShHXDF.js +0 -53
  96. package/dist/assets/MarkdownRenderer-kStoDRNE-D6ShHXDF.js.map +0 -1
  97. package/dist/assets/TagInformation-DibgRiob.js +0 -2
  98. package/dist/assets/UserStats-BMGNG7x3.js +0 -2
  99. package/dist/assets/admin-C4Ua7x6R.js +0 -4
  100. package/dist/assets/chess-Lfm7Fsvs-5pbFi0-y.js +0 -1
  101. package/dist/assets/common-ui.es-0v3pK9MO.js +0 -1
  102. package/dist/assets/common-ui.es-BNWvg8Db.js.map +0 -1
  103. package/dist/assets/dist-BFT7J5fx.js +0 -1
  104. package/dist/assets/dist-BIG2z9Yo.js +0 -18
  105. package/dist/assets/dist-CIgUAYYy.js.map +0 -1
  106. package/dist/assets/dist-D_cPFAOj.js +0 -1
  107. package/dist/assets/dist-otyR79at.js.map +0 -1
  108. package/dist/assets/edit-ui.es-CcjPb9cO.js +0 -1
  109. package/dist/assets/edit-ui.es-D0RNDqcl.js +0 -36
  110. package/dist/assets/edit-ui.es-D0RNDqcl.js.map +0 -1
  111. package/dist/assets/french-evUMlbbq-CmdXHGPK.js +0 -1
  112. package/dist/assets/index-HZf9vYUM.js +0 -4
  113. package/dist/assets/index-HZf9vYUM.js.map +0 -1
  114. package/dist/assets/math-B4HbgYf6-DOuMgmiQ.js +0 -34
  115. package/dist/assets/math-B4HbgYf6-DOuMgmiQ.js.map +0 -1
  116. package/dist/assets/math-DYni7rRl-DZKNTT_I.js +0 -1
  117. package/dist/assets/piano-BN5Btq91-kiaeJhGB.js +0 -1
  118. package/dist/assets/piano-DF1g6yaX-CAYlAEmp.js +0 -2
  119. package/dist/assets/pitch-Dn0iNqiS-DrRXHh5V.js +0 -1
  120. package/dist/assets/sightsing-CJX3k0Fd-nfWf5BKe.js +0 -1
  121. package/dist/assets/typing-k-ojjO7G-BkgFAffT.js +0 -1
  122. package/dist/assets/word-work-BOnRlZgd-I_fnRmvE.js +0 -2
  123. package/dist/assets/word-work-Dd6tIKrt-CQlqIXEs.js +0 -1
  124. /package/dist/assets/{math-B4HbgYf6-CZyvKZtp.css → math-D_8HiEQR-CZyvKZtp.css} +0 -0
@@ -0,0 +1,4 @@
1
+ import"./chunk-D6hFPZc3.js";import{$ as e,C as t,H as n,Ht as r,K as i,Lt as a,N as o,S as s,T as c,W as l,Z as u,_ as d,b as f,f as p,ft as m,g as h,gt as g,l as _,ut as v,v as y,y as b,z as x,zt as S}from"./vue.runtime.esm-bundler--Fxmd6l9.js";import{kt as C,y as w}from"./dist-BnMJdH50.js";var T={cardHistory:`cardH`,scheduled:`card_review_`,session:`SESSION::`,strategyState:`STRATEGY_STATE::`,registrations:`CourseRegistrations`};function toIsoTimestamp(e){if(typeof e==`number`)return new Date(e).toISOString();let t=String(e??``),n=Date.parse(t);return Number.isNaN(n)?t:new Date(n).toISOString()}function dumpFileName(e){return`userdb-${e.username}-${e.fetchedAt.slice(0,16).replace(`:`,``)}Z.json`}function parseLearnerDump(e){let t=JSON.parse(e);if(!t||typeof t.username!=`string`||!Array.isArray(t.docs))throw Error("[diagnostics] Not a learner dump: expected `username` and a `docs` array");return t}function questionTypeOf(e){if(typeof e!=`string`)return;let t=e.split(`.`);return t.length>=2?t[t.length-2]:e}function summarizeCards(e){let t=new Map(e.displayableData.map(e=>[e._id,e])),n=new Map;for(let r of e.cards){let e={};for(let n of t.get(r.id_displayable_data?.[0]??``)?.data??[])e[n.name]=n.data;n.set(r._id,{cardId:r._id,questionType:questionTypeOf(r.id_view),elo:r.elo,tags:[],data:e})}for(let t of e.tags)for(let e of t.taggedCards??[])n.get(e)?.tags.push(t.name);return n}function inferCourseId(e){if(e.courseId)return e.courseId;if(e.course)return e.course.courseId;let t=new Map;for(let n of e.docs)n._id.startsWith(T.session)&&typeof n.courseId==`string`&&t.set(n.courseId,(t.get(n.courseId)??0)+1);return[...t.entries()].sort((e,t)=>t[1]-e[1])[0]?.[0]}function fromDump(e,t){let n=t??inferCourseId(e);if(!n)throw Error(`[diagnostics] No course id given, and none found in the dump`);let r=[],i=[],a=[],o={},s;for(let t of e.docs){let e=t._id;if(e.startsWith(T.session))t.courseId===n&&r.push(t);else if(e.startsWith(T.cardHistory)){if(t.courseID!==n)continue;let e=t;i.push({...e,records:(e.records??[]).map(e=>({...e,timeStamp:toIsoTimestamp(e.timeStamp)})).sort((e,t)=>e.timeStamp.localeCompare(t.timeStamp))})}else if(e.startsWith(T.scheduled))t.courseId===n&&a.push(t);else if(e.startsWith(T.strategyState)){let[,r,i]=e.split(`::`);r===n&&i&&(o[i]=t.data)}else e===T.registrations&&(s=t)}return r.sort((e,t)=>e.startTime.localeCompare(t.startTime)),a.sort((e,t)=>String(e.reviewTime).localeCompare(String(t.reviewTime))),{username:e.username,courseId:n,asOf:e.fetchedAt,sessions:r,cardHistories:i,scheduled:a,registration:s,strategyState:o,tombstones:(e.tombstones??[]).map(({id:e,seq:t})=>({id:e,seq:t})),...e.course&&e.course.courseId===n?{cards:summarizeCards(e.course),...e.course.strategies?{strategies:e.course.strategies}:{}}:{}}}function userDbName(e){let t=``;for(let n of new TextEncoder().encode(e))t+=n.toString(16).padStart(2,`0`);return`userdb-`+t}function base64(e){let t=``;for(let n of new TextEncoder().encode(e))t+=String.fromCharCode(n);return btoa(t)}function trimTrailingSlashes(e){let t=e.length;for(;t>0&&e[t-1]===`/`;)t--;return e.slice(0,t)}function couchReader(e){let t=e.fetchImpl??fetch,n=trimTrailingSlashes(e.couchUrl),r={Accept:`application/json`};e.auth.kind===`basic`&&(r.Authorization=`Basic `+base64(`${e.auth.username}:${e.auth.password}`));let i=e.auth.kind===`cookie`?`include`:void 0;async function get(e,a={}){let o=await t(`${n}/${e}`,{method:a.method??`GET`,headers:a.body?{...r,"Content-Type":`application/json`}:r,...a.body?{body:JSON.stringify(a.body)}:{},...i?{credentials:i}:{}});if(!o.ok){let t=await o.text().catch(()=>``);throw Error(`[diagnostics] ${a.method??`GET`} ${e} -> ${o.status} ${t}`)}return await o.json()}async function byKeys(e,t){let n=[];for(let r=0;r<t.length;r+=500){let i=await get(`${e}/_all_docs?include_docs=true`,{method:`POST`,body:{keys:t.slice(r,r+500)}});for(let e of i.rows)e.doc&&n.push(e.doc)}return n}async function byPrefix(e,t){return(await get(`${e}/_all_docs?${new URLSearchParams({include_docs:`true`,startkey:JSON.stringify(t),endkey:JSON.stringify(t+`￰`)})}`)).rows.map(e=>e.doc).filter(e=>!!e)}return{base:n,get,byKeys,byPrefix}}function touchedCardIds(e){let t=new Set;for(let n of e)if(n._id.startsWith(`cardH`)&&typeof n.cardID==`string`)t.add(n.cardID);else if(n._id.startsWith(`card_review_`)&&typeof n.cardId==`string`)t.add(n.cardId);else if(n._id.startsWith(`SESSION::`)&&Array.isArray(n.eloEvents))for(let e of n.eloEvents)e.cardId&&t.add(e.cardId);return[...t]}async function fetchLearnerDump(e){let t=couchReader(e),n=userDbName(e.username),r=new Date().toISOString(),i=await t.get(n),a=new URLSearchParams({include_docs:`true`});e.attachments&&a.set(`attachments`,`true`);let o=(await t.get(`${n}/_all_docs?${a}`)).rows.map(e=>e.doc).filter(e=>!!e),s=(await t.get(`${n}/_changes?style=main_only`)).results.filter(e=>e.deleted).map(e=>({id:e.id,rev:e.changes[0]?.rev,seq:Number(String(e.seq).split(`-`)[0])})),c=e.cards??`touched`,l;if(c!==`none`){let n=`coursedb-${e.courseId}`,r;r=c===`all`?(await t.get(`${n}/_find`,{method:`POST`,body:{selector:{docType:`CARD`},limit:1e6}})).docs:await t.byKeys(n,touchedCardIds(o));let i=new Set(r.map(e=>e._id)),a=new Set;for(let e of r)for(let t of e.id_displayable_data??[])a.add(t);let s=await t.byKeys(n,[...a]),u=(await t.byPrefix(n,`TAG`)).map(e=>{let t=Array.isArray(e.taggedCards)?e.taggedCards:[];return{...e,taggedCount:t.length,taggedCards:c===`all`?t:t.filter(e=>i.has(e))}}).filter(e=>c===`all`||e.taggedCards.length>0),d=await t.byPrefix(n,`NAVIGATION_STRATEGY`);l={courseId:e.courseId,source:`${t.base}/${n}`,scope:c,cards:r,displayableData:s,tags:u,strategies:d}}return{formatVersion:1,username:e.username,dbName:n,source:t.base,fetchedAt:r,courseId:e.courseId,info:i,docs:o,tombstones:s,...l?{course:l}:{}}}var isSkillTag=(e,t)=>e?.isSkillTag?.(t)??!1,shortTag=(e,t)=>e?.shortTag?.(t)??t;function bySkillThenName(e){return(t,n)=>{let r=Number(isSkillTag(e,n))-Number(isSkillTag(e,t));return r===0?t.localeCompare(n):r}}function defaultSnapshotMetrics(e){let t={};for(let[n,r]of Object.entries(e))if(typeof r==`number`)t[n]=r;else if(r&&typeof r==`object`&&!Array.isArray(r))for(let[e,i]of Object.entries(r))typeof i==`number`&&(t[`${n}.${e}`]=i);return t}var E={churned:{label:`Churned`,help:`Many pipeline runs relative to cards served: the plan kept being rebuilt rather than consumed.`},"out-of-content":{label:`Out of content`,help:`Ended with time left on the clock: content ran out before the session did.`},walked:{label:`Walked`,help:`Abandoned or never closed, after real time invested. Not a mis-click.`},stalled:{label:`Stalled`,help:`No progress metric moved and ELO was essentially flat. The sitting produced nothing measurable.`},grinding:{label:`Grinding`,help:`Majority-incorrect, or ended with unfinished cards still in the failed queue.`}},D={churnRunsPerCard:1/3,churnMinCards:4,outOfContentSeconds:20,walkMinCards:2,stallEloEpsilon:5,grindAccuracy:.5};function stateRows(e,t){let n=t?.snapshotMetrics??defaultSnapshotMetrics,r=e.stateAtStart?n(e.stateAtStart):{},i=e.stateAtEnd?n(e.stateAtEnd):{};return[...new Set([...Object.keys(r),...Object.keys(i)])].map(e=>{let t=r[e]??null,n=i[e]??null;return{label:e,from:t,to:n,delta:t!==null&&n!==null?n-t:null}})}function flagSession(e,t){let n=D,{doc:r,accuracy:i,eloNet:a}=e,o=[],s=r.tally?.cardsPresented??0,c=r.runs?.length??0;s>=n.churnMinCards&&c/s>n.churnRunsPerCard&&o.push(`churned`),r.status===`closed`&&(r.tally?.secondsRemaining??0)>n.outOfContentSeconds&&o.push(`out-of-content`),(r.status===`open`||r.status===`abandoned`&&s>=n.walkMinCards)&&o.push(`walked`);let l=e.state.filter(e=>t?.progressMetrics?.includes(e.label)),u=a!==null||l.some(e=>e.delta!==null);return s>0&&u&&l.every(e=>(e.delta??0)===0)&&Math.abs(a??0)<n.stallEloEpsilon&&o.push(`stalled`),(i!==null&&i<n.grindAccuracy&&s>0||(r.tally?.failedQRemaining??0)>0)&&o.push(`grinding`),o}function summarizeSession(e,t){let n=Date.parse(e.startTime),r=e.endTime?Date.parse(e.endTime):NaN,i=Number.isNaN(n)||Number.isNaN(r)?null:Math.round((r-n)/1e3),a=e.tally?.responses??0,o=a>0?(e.tally?.correct??0)/a:null,s=e.eloEvents??[],c={doc:e,durationSeconds:i,accuracy:o,eloNet:s.length?s.reduce((e,t)=>e+(t.global.after-t.global.before),0):null,state:stateRows(e,t)};return{...c,flags:flagSession(c,t)}}function summarizeSessions(e,t){return e.sessions.map(e=>summarizeSession(e,t)).reverse()}function toResponseEloDelta(e,t){let n=bySkillThenName(t),r=Object.entries(e.tags??{}).map(([e,t])=>({tag:e,before:t.before,after:t.after,delta:t.after-t.before,score:t.score})).sort((e,t)=>n(e.tag,t.tag));return{userScore:e.userScore,global:{before:e.global.before,after:e.global.after,delta:e.global.after-e.global.before},...e.card?{card:{before:e.card.before,after:e.card.after,delta:e.card.after-e.card.before}}:{},tags:r}}function attachEloEvents(e,t,n){let r=new Set;for(let i of t){let t=Date.parse(i.at),a=-1,o=1/0;e.forEach((e,n)=>{if(r.has(n)||e.cardId!==i.cardId)return;let s=Math.abs(Date.parse(e.at)+e.timeSpentMs-t);s<o&&(o=s,a=n)}),a>=0&&(r.add(a),e[a].elo=toResponseEloDelta(i,n))}}function byTime(e,t){let n=Date.parse(e.at),r=Date.parse(t.at);return Number.isNaN(n)||Number.isNaN(r)?e.at.localeCompare(t.at):n-r}function sessionDetail(e,t,n){let r=e.sessions.find(e=>e.sessionId===t);if(!r)return null;let i=[];for(let r of e.cardHistories){let a=e.cards?.get(r.cardID);for(let e of r.records)e.sessionId===t&&i.push({kind:`response`,at:e.timeStamp,cardId:r.cardID,...a?{card:a,questionType:a.questionType}:{},tags:a?[...a.tags].sort(bySkillThenName(n)):[],isCorrect:typeof e.isCorrect==`boolean`?e.isCorrect:null,timeSpentMs:e.timeSpent??0,priorAttempts:typeof e.priorAttemps==`number`?e.priorAttemps:null,userAnswer:e.userAnswer})}r.eloEvents?.length&&attachEloEvents(i,r.eloEvents,n);let a=[...(r.runs??[]).map(e=>({kind:`run`,at:e.at,run:e})),...i].sort(byTime);return{summary:summarizeSession(r,n),timeline:a,responsesMissing:(r.tally?.responses??0)>i.length}}function servedTags(e,t){let n=new Map;for(let t of e)if(t.kind===`response`)for(let e of t.tags){let r=n.get(e);r||(r={responses:0,correct:0,incorrect:0,totalTimeMs:0,cards:new Set},n.set(e,r)),r.responses+=1,r.totalTimeMs+=t.timeSpentMs,r.cards.add(t.cardId),t.isCorrect===!0?r.correct+=1:t.isCorrect===!1&&(r.incorrect+=1)}return[...n.entries()].map(([e,t])=>{let n=t.correct+t.incorrect;return{tag:e,responses:t.responses,correct:t.correct,incorrect:t.incorrect,accuracy:n>0?t.correct/n:null,totalTimeMs:t.totalTimeMs,cards:t.cards.size}}).sort((e,n)=>{let r=Number(isSkillTag(t,n.tag))-Number(isSkillTag(t,e.tag));return r===0?n.responses===e.responses?e.tag.localeCompare(n.tag):n.responses-e.responses:r})}function eloLedger(e){let t={count:0,net:0,gained:0,lost:0,wins:0,losses:0};for(let n of e){if(n.kind!==`response`||!n.elo)continue;let e=n.elo.global.delta;t.count+=1,t.net+=e,e>0?(t.gained+=e,t.wins+=1):e<0&&(t.lost+=e,t.losses+=1)}return t.count?t:null}var O=3;function cardDossiers(e){let t=Date.parse(e.asOf),n=new Map;for(let t of e.scheduled){let e=String(t.reviewTime),r=n.get(t.cardId);(!r||e<r)&&n.set(t.cardId,e)}return e.cardHistories.map(r=>{let i=e.cards?.get(r.cardID),a=r.records.filter(e=>e.isCorrect===!1).length,o=r.records.reduce((e,t)=>e+(t.timeSpent??0),0),s=n.get(r.cardID),c=s?{reviewTime:s,overdue:Date.parse(s)<=t}:null,l=i?.elo?.global?.score??null,u=i?.elo?.global?.count??null;return{cardId:r.cardID,...i?{card:i}:{},records:r.records,lapses:r.lapses??0,streak:r.streak??0,bestIntervalSeconds:r.bestInterval??0,attempts:r.records.length,fails:a,firstSeen:r.records[0]?.timeStamp??null,lastSeen:r.records[r.records.length-1]?.timeStamp??null,totalTimeMs:o,pendingReview:c,cardElo:l,cardEloCount:u,stuck:a>0&&!!c?.overdue,frozenElo:a>=O&&u!==null&&u<a,painScore:o*(a+1)}}).sort((e,t)=>t.painScore-e.painScore)}function recordPerformance(e){let t=e.performance;return typeof t==`number`?t:t&&typeof t==`object`&&typeof t._global==`number`?t._global:null}function runCardSource(e){return e.required?`required: ${e.required}`:e.generator??`unknown`}function selectedBySource(e){let t=new Map;for(let n of e.cards??[]){if(!n.selected)continue;let e=runCardSource(n);t.set(e,(t.get(e)??0)+1)}return[...t].map(([e,t])=>({source:e,count:t})).sort((e,t)=>t.count-e.count)}function pipelineRunStats(e,t={}){let n=e.sessions.filter(e=>!t.since||e.startTime>=t.since),r=new Map;for(let t of e.cardHistories)for(let e of t.records){if(!e.sessionId)continue;let n=r.get(e.sessionId)??[];n.push({cardId:t.cardID,record:e}),r.set(e.sessionId,n)}let i=new Map,gen=e=>{let t=i.get(e);return t||(t={name:e,runs:0,cards:0,newCards:0,reviewCards:0,topScoreMax:0,topScoreLast:0,selected:0,firstAttempts:0,firstAttemptsCorrect:0},i.set(e,t)),t},a=new Map,o=new Map,s=0,c=0,l=0,u,d;for(let e of n){let t=new Map;for(let n of e.runs??[]){s++,(!u||n.at<u)&&(u=n.at),(!d||n.at>d)&&(d=n.at);for(let e of n.generators??[]){let t=gen(e.name);t.runs++,t.cards+=e.cardCount,t.newCards+=e.newCount,t.reviewCards+=e.reviewCount,t.topScoreMax=Math.max(t.topScoreMax,e.topScore),t.topScoreLast=e.topScore}for(let e of n.filters??[]){let t=a.get(e.name)??{name:e.name,runs:0,boosted:0,penalized:0,passed:0,removed:0};t.runs++,e.kind&&(t.kind=e.kind),t.boosted+=e.boosted,t.penalized+=e.penalized,t.passed+=e.passed,t.removed+=e.removed,a.set(e.name,t)}for(let e of n.regulators??[]){let t=o.get(e.name)??{name:e.name,class:e.class,runs:0,meanMultiplier:0,maxMultiplier:0,runsActive:0,last:e,sumMultiplier:0};t.runs++,t.sumMultiplier+=e.multiplier,t.maxMultiplier=Math.max(t.maxMultiplier,e.multiplier),e.multiplier>1&&t.runsActive++,t.last=e,o.set(e.name,t)}if(n.cards){c++;for(let e of n.cards)if(e.selected){if(!e.generator){l++;continue}gen(e.generator).selected++,t.has(e.cardId)||t.set(e.cardId,e.generator)}}}for(let{cardId:n,record:i}of r.get(e.sessionId)??[]){let e=t.get(n);if(!e||i.priorAttemps!==0)continue;let r=gen(e);r.firstAttempts++,i.isCorrect===!0&&r.firstAttemptsCorrect++}}return{sessions:n.length,runs:s,runsWithSelection:c,firstRunAt:u,lastRunAt:d,generators:[...i.values()].map(({cards:e,newCards:t,reviewCards:n,...r})=>({...r,meanCards:r.runs?e/r.runs:0,meanNew:r.runs?t/r.runs:0,meanReview:r.runs?n/r.runs:0})).sort((e,t)=>t.runs-e.runs||e.name.localeCompare(t.name)),filters:[...a.values()].sort((e,t)=>e.name.localeCompare(t.name)),regulators:[...o.values()].map(({sumMultiplier:e,...t})=>({...t,meanMultiplier:t.runs?e/t.runs:0})),selectedUnattributed:l}}function fmtDelta(e){if(e===null)return`—`;if(e===0)return`0`;let t=Number.isInteger(e)?e:Number(e.toFixed(1));return t>0?`+${t}`:String(t)}function fmtDuration(e){let t=Math.max(0,Math.round(e));if(t<60)return`${t}s`;let n=Math.floor(t/60);return n<60?t%60?`${n}m${t%60}s`:`${n}m`:`${(n/60).toFixed(1)}h`}function fmtAnswer(e,t=40){if(e==null)return``;if(typeof e==`string`||typeof e==`number`)return String(e);try{let n=JSON.stringify(e);return n.length>t?`${n.slice(0,t)}\u2026`:n}catch{return String(e)}}function fmtScore(e){return e===null||!Number.isFinite(e)?`∞`:Math.abs(e)>=.01||e===0?e.toFixed(2):e.toExponential(1)}function trailText(e,t){let n=[` ${e}: ${t.cardId} (${t.origin}, ${runCardSource(t)}) final ${fmtScore(t.score)}`];for(let e of t.trail)n.push(` ${e.action} ${e.strategyName} \u2192 ${fmtScore(e.score)}: ${e.reason}`);return n}function regulatorText(e){let t=e.inputs;if(e.name===`review-mass`)return`review mass ${e.urgency.toFixed(1)} over ${t.due??e.applied} due (healthy ${t.healthyMass}) \u2192 \xD7${e.multiplier.toFixed(2)}`;let n=t.frozenHours?`, ${t.frozenHours.toFixed(1)}h frozen`:``;return`intake ${e.urgency.toFixed(1)}h since a new card${n}; ${t.eligibleNew??e.applied}/${t.newCandidates??`?`} new eligible \u2192 \xD7${e.multiplier.toFixed(2)}`}function runText(e){let t=[];if(t.push(`RUN ${e.label}${e.mode?` [${e.mode}]`:``} @ ${e.at} \u2014 generated ${e.generatedCount} \u2192 selected ${e.finalCount} (${e.newSelected} new, ${e.reviewsSelected} review)`+(e.generatedCount>0&&e.finalCount===0?` ⚠ nothing survived`:``)),typeof e.userElo==`number`&&t.push(` userElo: ${Math.round(e.userElo)}`),e.versions&&t.push(` versions: strategies ${e.versions.strategies??`—`} \xB7 content ${e.versions.content??`—`}`),e.generators?.length){t.push(` generators:`);for(let n of e.generators)t.push(` - ${n.name}: ${n.cardCount} cards (${n.newCount} new, ${n.reviewCount} review), topScore ${n.topScore.toFixed(2)}`)}if(e.filters?.length){t.push(` filters:`);for(let n of e.filters)t.push(` - ${n.name}${n.kind?` (${n.kind})`:``}: +${n.boosted} boosted, -${n.penalized} penalized, ${n.passed} passed, ${n.removed} removed`)}if(e.regulators?.length){t.push(` regulators:`);for(let n of e.regulators)t.push(` - ${regulatorText(n)}`)}if(e.hints&&t.push(` hints: ${JSON.stringify(e.hints)}`),e.cards?.length){let n=selectedBySource(e).map(e=>`${e.source} ${e.count}`);n.length&&t.push(` selected by source: ${n.join(` · `)}`),t.push(` selection (✓ selected, · runner-up):`);for(let n of e.cards)t.push(` ${n.selected?`✓`:`·`} ${n.cardId} (${n.origin}, ${runCardSource(n)}) ${fmtScore(n.score)}`)}if(e.unselectedNew?.nextInLine&&t.push(...trailText(`next new in line`,e.unselectedNew.nextInLine)),e.unselectedNew?.topGenerated&&t.push(...trailText(`top-generated new (sunk)`,e.unselectedNew.topGenerated)),e.discardedTail){let n=e.discardedTail;t.push(` discardedTail: ${n.count} cards`+(n.scoreRange?` \xB7 score [${n.scoreRange[0].toFixed(2)}, ${n.scoreRange[1].toFixed(2)}]`:``)+(n.eloRange?` \xB7 elo [${Math.round(n.eloRange[0])}, ${Math.round(n.eloRange[1])}]`:``)),n.note&&t.push(` ${n.note}`)}return t.join(`
2
+ `)}function scoredTagDeltas(e){return e.tags.filter(e=>e.score!==null&&e.delta!==0).slice(0,4)}function eloSuffix(e,t){if(!e)return``;let n=`ELO g:${e.global.before}\u2192${e.global.after} (${fmtDelta(e.global.delta)})`,r=scoredTagDeltas(e).map(e=>`${shortTag(t,e.tag)}:${fmtDelta(e.delta)}`);return` ${n}${r.length?` | ${r.join(` `)}`:``}`}function clock(e){let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toISOString().slice(11,19)}function sessionText(e,t,n={},r){let i=t.summary,a=i.doc,o=t.timeline.filter(e=>e.kind===`response`).length,s=[];if(s.push(`# Study session ${a.sessionId} \u2014 user ${e}`),s.push(``),s.push(`## Legend`),s.push(`- The TIMELINE is one time-ordered stream: RUN lines are pipeline (re)plans;`),s.push(` the lines between them are card responses in the order presented.`),s.push(`- RUN "generated N → selected M (a new, b review)": the pipeline produced N`),s.push(` candidates and chose M. "nothing survived" = generated > 0 but 0 selected.`),s.push(` Bootstrap runs fire before card #1; replans are interleaved by time.`),s.push(`- generators: each source's contribution. filters: how each reshaped scores`),s.push(` (gate: not ready yet; signal: preference). regulators: the pressure on each class,`),s.push(` review mass (due reviews by value) and intake (hours since a new card).`),s.push(` hints: the ReplanHints the navigator was told (_label = replan reason).`),s.push(` versions: the strategy docs' hash and the content version the run ran on; the`),s.push(` headline's are the framework and app versions. A change between runs marks a deploy.`),s.push(` selection: the chosen cards and top runners-up. "next new in line" / "top-generated`),s.push(` new (sunk)": the unselected new cards worth explaining, with each score change.`),s.push(` Each card reads (origin, source). origin: review = a scheduled review, new = anything`),s.push(` else. source: the generator that produced it, or "required: <hint>" when a hint forced`),s.push(` it. Older runs show origin "unknown" for prescribed and hint-required cards.`),s.push(`- RESP "✓/✗ type <cardId> [tags] Ts (attempt k) 'answer'": one presentation and`),s.push(` its outcome. A trailing "ELO g:before→after (Δ) | tag:Δ …" is the exchange it`),s.push(` produced. Only first attempts move ELO.`),s.push(``),s.push(`## Headline`),s.push(`- status: ${a.status}`),s.push(`- start: ${a.startTime}${a.endTime?` \xB7 end: ${a.endTime}`:``}`),a.versions&&s.push(`- versions: framework ${a.versions.framework}`+(a.versions.app?` \xB7 app ${a.versions.app}`:``)),s.push(`- clock: ${i.durationSeconds??`—`}s of ${a.plannedSeconds}s planned`+(a.tally?` \xB7 ${a.tally.secondsRemaining}s remaining`:``)),a.tally&&s.push(`- tally: ${a.tally.cardsPresented} cards, ${a.tally.responses} responses (${a.tally.correct} correct / ${a.tally.incorrect} incorrect) \xB7 failedQ remaining ${a.tally.failedQRemaining}`),s.push(`- flags: ${i.flags.length?i.flags.join(`, `):`none`}`),s.push(`- config: batchLimit ${a.config?.defaultBatchLimit??`?`}, ${a.config?.sourceCount??`?`} source(s), opening queues supply ${a.initialQueues?.supplyQ??`?`} / failed ${a.initialQueues?.failedQ??`?`}`),t.responsesMissing&&s.push(`- \u26A0 responsesMissing: tally claims ${a.tally?.responses} responses but only ${o} stamped records were found.`),s.push(``),i.state.length){s.push(`## Learner state (start → end, Δ)`);for(let e of i.state)s.push(`- ${e.label}: ${e.from??`—`} \u2192 ${e.to??`—`} (${fmtDelta(e.delta)})`);s.push(``)}if(s.push(`## Session hints`),s.push(`- at open: ${a.config?.initHints?JSON.stringify(a.config.initHints):`none`}`),s.push(`- at close: ${a.finalHints?JSON.stringify(a.finalHints):`none`}`),s.push(``),n.servedTags?.length){s.push(`## Served tags`);for(let e of n.servedTags)s.push(`- ${e.tag}: ${e.responses} resp / ${e.cards} card(s), acc ${e.accuracy===null?`n/a`:`${Math.round(e.accuracy*100)}%`} (${e.correct}\u2713/${e.incorrect}\u2717), ${(e.totalTimeMs/1e3).toFixed(1)}s`);s.push(``)}let c=n.eloLedger;c&&(s.push(`## ELO ledger (learner global)`),s.push(`- net ${fmtDelta(c.net)} across ${c.count} exchange(s) \xB7 gained ${fmtDelta(c.gained)} over ${c.wins} win(s) \xB7 lost ${fmtDelta(c.lost)} over ${c.losses} loss(es)`),s.push(``)),s.push(`## Timeline (${t.timeline.length} entries)`);for(let e of t.timeline){if(e.kind===`run`){s.push(runText(e.run));continue}let t=e.isCorrect===!0?`✓`:e.isCorrect===!1?`✗`:`·`,n=e.tags.length?` [${e.tags.join(`, `)}]`:``,i=e.priorAttempts?` (attempt ${e.priorAttempts+1})`:``,a=e.userAnswer==null?``:` '${fmtAnswer(e.userAnswer)}'`;s.push(`RESP ${clock(e.at)} ${t} ${e.questionType??`card`} ${e.cardId}${n} \u2014 ${(e.timeSpentMs/1e3).toFixed(1)}s${i}${a}${eloSuffix(e.elo,r)}`)}return s.join(`
3
+ `)}var k=Object.defineProperty,__name=(e,t)=>k(e,`name`,{value:t,configurable:!0});function useLearnerDataset(){let e=m(null),t=m(null),n=v(!1),r=v(null);async function load(i,a){n.value=!0,r.value=null;try{let n=await i();t.value=fromDump(n,a),e.value=n}catch(e){r.value=e instanceof Error?e.message:String(e)}finally{n.value=!1}}function loadFromCouch(e){return load(()=>fetchLearnerDump({...e,auth:{kind:`cookie`}}),e.courseId)}function loadFromFile(e,t){return load(async()=>parseLearnerDump(await e.text()),t)}return{dump:e,dataset:t,loading:n,error:r,loadFromCouch,loadFromFile}}function downloadLearnerDump(e){let t=new Blob([JSON.stringify(e,null,2)],{type:`application/json`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=dumpFileName(e),r.click(),URL.revokeObjectURL(n)}var A={class:`d-flex flex-wrap align-center ga-2`},j={key:1,class:`d-flex flex-wrap align-center ga-2 mt-3`},M=c({__name:`LearnerDatasetSource`,props:{couchUrl:{},courseId:{},initialUsername:{},autoload:{type:Boolean}},emits:[`loaded`],setup(a,{emit:o}){let c=a,l=o,{dump:m,dataset:S,loading:C,error:w,loadFromCouch:T,loadFromFile:E}=useLearnerDataset(),D=v(c.initialUsername??``),O=v(null),k=h(()=>{let e=S.value?.sessions??[];return e.length?`${e[0].startTime.slice(0,10)} .. ${e[e.length-1].startTime.slice(0,10)}`:``});function loadLive(){!c.couchUrl||!c.courseId||!D.value||T({couchUrl:c.couchUrl,courseId:c.courseId,username:D.value})}function onFile(e){let t=e.target,n=t.files?.[0];n&&E(n,c.courseId),t.value=``}return u(S,e=>{e&&m.value&&l(`loaded`,e,m.value)}),x(()=>{c.autoload&&loadLive()}),(a,o)=>{let c=i(`v-text-field`),l=i(`v-btn`),u=i(`v-alert`),h=i(`v-spacer`),v=i(`v-card-text`),x=i(`v-card`);return n(),y(x,{variant:`outlined`},{default:e(()=>[t(v,null,{default:e(()=>[d(`div`,A,[t(c,{modelValue:D.value,"onUpdate:modelValue":o[0]||(o[0]=e=>D.value=e),label:`Learner`,density:`compact`,"hide-details":``,style:{"max-width":`16rem`},disabled:!a.couchUrl||!a.courseId,onKeydown:_(loadLive,[`enter`])},null,8,[`modelValue`,`disabled`]),t(l,{color:`primary`,loading:g(C),disabled:!a.couchUrl||!a.courseId||!D.value,onClick:loadLive},{default:e(()=>o[3]||(o[3]=[s(` Load `)])),_:1},8,[`loading`,`disabled`]),o[5]||(o[5]=d(`span`,{class:`text-medium-emphasis mx-2`},`or`,-1)),t(l,{variant:`tonal`,"prepend-icon":`mdi-file-upload-outline`,onClick:o[1]||(o[1]=e=>O.value?.click())},{default:e(()=>o[4]||(o[4]=[s(` Open dump file `)])),_:1}),d(`input`,{ref_key:`fileInput`,ref:O,type:`file`,accept:`.json,application/json`,hidden:``,onChange:onFile},null,544)]),g(w)?(n(),y(u,{key:0,type:`error`,variant:`tonal`,density:`compact`,class:`mt-3`},{default:e(()=>[s(r(g(w)),1)]),_:1})):b(``,!0),g(S)&&g(m)?(n(),f(`div`,j,[d(`span`,null,[d(`strong`,null,r(g(S).username),1),s(` · `+r(g(S).sessions.length)+` sessions `,1),k.value?(n(),f(p,{key:0},[s(`(`+r(k.value)+`)`,1)],64)):b(``,!0),s(` · `+r(g(S).cardHistories.length)+` cards seen · as of `+r(g(S).asOf.slice(0,16))+`Z `,1),g(S).cards?b(``,!0):(n(),f(p,{key:1},[s(`· no course slice`)],64))]),t(h),t(l,{variant:`text`,size:`small`,"prepend-icon":`mdi-download`,onClick:o[2]||(o[2]=e=>g(downloadLearnerDump)(g(m)))},{default:e(()=>o[6]||(o[6]=[s(` Save dump `)])),_:1})])):b(``,!0)]),_:1})]),_:1})}}}),N={churned:{icon:`mdi-autorenew`,color:`warning`},"out-of-content":{icon:`mdi-cup-off-outline`,color:`error`},walked:{icon:`mdi-exit-run`,color:`error`},stalled:{icon:`mdi-arrow-collapse-horizontal`,color:`grey`},grinding:{icon:`mdi-alert-octagon-outline`,color:`warning`}};function statusColor(e){return e===`closed`?`success`:e===`abandoned`?`warning`:`error`}function accuracyClass(e){return e===null?`text-disabled`:e>=.8?`text-success`:e<.5?`text-error`:``}function deltaClass(e){return e===null||e===0?`text-disabled`:e>0?`text-success`:`text-error`}function deltaColor(e){return e>0?`success`:e<0?`error`:`grey`}function fmtTime(e){if(!e)return`—`;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString()}function fmtClock(e){let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleTimeString(void 0,{hour12:!1})}function shortId(e,t=28){return e.length>t?`…${e.slice(-(t-2))}`:e}function useCopy(){let e=v(null),t=null;async function copy(n,r){try{await navigator.clipboard.writeText(n),e.value=r,t&&clearTimeout(t),t=setTimeout(()=>e.value=null,1400)}catch(e){console.warn(`[admin] clipboard write failed`,e)}}return{copied:e,copy}}var P={key:0,class:`text-caption mb-2`},F={class:`text-medium-emphasis`},I={class:`d-flex flex-wrap mb-2 ga-1`},L={key:0,class:`text-caption text-disabled`},R={class:`text-caption text-medium-emphasis mb-2`},z={key:0,class:`text-error`},B={class:`text-no-wrap`},V={key:2,class:`text-disabled`},ee={class:`text-truncate`,style:{"max-width":`200px`}},te=c({__name:`CardDossierDetail`,props:{dossier:{},interpreters:{}},setup(o){function perf(e){let t=recordPerformance(e);return t===null?`—`:t.toFixed(2)}function fmtInterval(e){return e?e<3600?`${Math.round(e/60)}m`:e<86400?`${Math.round(e/3600)}h`:`${Math.round(e/86400)}d`:`none`}return(o,c)=>{let u=i(`v-chip`),m=i(`v-icon`),h=i(`v-table`);return n(),f(`div`,null,[o.dossier.card&&Object.keys(o.dossier.card.data).length?(n(),f(`div`,P,[(n(!0),f(p,null,l(o.dossier.card.data,(e,t)=>(n(),f(`span`,{key:t,class:`mr-3`},[d(`span`,F,r(t)+`:`,1),s(` `+r(g(fmtAnswer)(e,60)),1)]))),128))])):b(``,!0),d(`div`,I,[(n(!0),f(p,null,l(o.dossier.card?.tags??[],t=>(n(),y(u,{key:t,size:`x-small`,variant:`outlined`,color:g(isSkillTag)(o.interpreters,t)?`primary`:void 0},{default:e(()=>[s(r(t),1)]),_:2},1032,[`color`]))),128)),o.dossier.card?b(``,!0):(n(),f(`span`,L,`no course data in this dataset`))]),d(`div`,R,[s(` lapses `+r(o.dossier.lapses)+` · streak `+r(o.dossier.streak)+` · best interval `+r(fmtInterval(o.dossier.bestIntervalSeconds))+` · `,1),o.dossier.pendingReview?(n(),f(p,{key:0},[s(` next review `+r(g(fmtTime)(o.dossier.pendingReview.reviewTime))+` `,1),o.dossier.pendingReview.overdue?(n(),f(`span`,z,`(overdue)`)):b(``,!0)],64)):(n(),f(p,{key:1},[s(`no review scheduled`)],64))]),t(h,{density:`compact`,class:`sk-record-table`},{default:e(()=>[c[2]||(c[2]=d(`thead`,null,[d(`tr`,null,[d(`th`,null,`#`),d(`th`,null,`When`),d(`th`,null,`Result`),d(`th`,null,`Perf`),d(`th`,null,`Prior att.`),d(`th`,null,`Time`),d(`th`,null,`Answer`)])],-1)),d(`tbody`,null,[(n(!0),f(p,null,l(o.dossier.records,(t,i)=>(n(),f(`tr`,{key:i,class:a(t.isCorrect===!1?`sk-fail-row`:``)},[d(`td`,null,r(i+1),1),d(`td`,B,r(g(fmtTime)(t.timeStamp)),1),d(`td`,null,[t.isCorrect===!0?(n(),y(m,{key:0,size:`small`,color:`success`},{default:e(()=>c[0]||(c[0]=[s(`mdi-check`)])),_:1})):t.isCorrect===!1?(n(),y(m,{key:1,size:`small`,color:`error`},{default:e(()=>c[1]||(c[1]=[s(`mdi-close`)])),_:1})):(n(),f(`span`,V,`—`))]),d(`td`,null,r(perf(t)),1),d(`td`,null,r(t.priorAttemps??`—`),1),d(`td`,null,r(((t.timeSpent??0)/1e3).toFixed(1))+`s`,1),d(`td`,ee,r(g(fmtAnswer)(t.userAnswer)),1)],2))),128))])]),_:1})])}}}),H=__name((e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},`default`),U=H(te,[[`__scopeId`,`data-v-76b0a622`]]),W={class:`text-caption text-medium-emphasis mb-4`},G={class:`text-h6`},K={class:`text-caption`},q={class:`d-flex align-center flex-wrap mb-3 ga-3`},J={class:`d-flex align-center flex-wrap ga-2`,style:{width:`100%`}},Y={class:`text-body-2 font-weight-medium`},X={class:`text-caption text-medium-emphasis`},Z={key:2,class:`text-caption`},Q={key:0,class:`ml-1 text-disabled`},ne=H(c({__name:`LearnerCardHistory`,props:{dataset:{},interpreters:{},focus:{}},setup(c){let m=c,_=h(()=>cardDossiers(m.dataset)),x=v(`all`),S=v(``),C=v([]),w=v(null),T=h(()=>({stuck:_.value.filter(e=>e.stuck).length,failed:_.value.filter(e=>e.fails>0).length,frozen:_.value.filter(e=>e.frozenElo).length})),E=h(()=>[{label:`cards seen`,value:_.value.length,color:`primary`},{label:`total attempts`,value:_.value.reduce((e,t)=>e+t.attempts,0),color:`primary`},{label:`total fails`,value:_.value.reduce((e,t)=>e+t.fails,0),color:`error`},{label:`time on cards`,value:fmtDuration(_.value.reduce((e,t)=>e+t.totalTimeMs,0)/1e3),color:`grey`},{label:`stuck reviews`,value:T.value.stuck,color:`error`},{label:`frozen ELO`,value:T.value.frozen,color:`warning`}]),D=h(()=>{let e=_.value;x.value===`stuck`?e=e.filter(e=>e.stuck):x.value===`failed`?e=e.filter(e=>e.fails>0):x.value===`frozen`&&(e=e.filter(e=>e.frozenElo));let t=S.value?.trim().toLowerCase();return t&&(e=e.filter(e=>e.cardId.toLowerCase().includes(t)||(e.card?.questionType??``).toLowerCase().includes(t)||(e.card?.tags??[]).some(e=>e.toLowerCase().includes(t))||Object.values(e.card?.data??{}).some(e=>typeof e==`string`&&e.toLowerCase().includes(t)))),e});function headline(e){let t=Object.values(e.card?.data??{}).find(e=>typeof e==`string`&&e.length<=40);return typeof t==`string`?t:``}async function applyFocus(e){!e||!_.value.some(t=>t.cardId===e)||(x.value=`all`,S.value=e,C.value=[e],await o(),document.querySelector(`[data-card="${CSS.escape(e)}"]`)?.scrollIntoView({behavior:`smooth`,block:`center`}),w.value=e,setTimeout(()=>{w.value===e&&(w.value=null)},2200))}return u(()=>m.focus,e=>void applyFocus(e),{immediate:!0}),(o,c)=>{let u=i(`v-icon`),m=i(`v-card`),h=i(`v-col`),v=i(`v-row`),O=i(`v-btn`),k=i(`v-btn-toggle`),A=i(`v-text-field`),j=i(`v-alert`),M=i(`v-spacer`),N=i(`v-chip`),P=i(`v-expansion-panel-title`),F=i(`v-expansion-panel-text`),I=i(`v-expansion-panel`),L=i(`v-expansion-panels`);return n(),f(`div`,null,[d(`p`,W,[c[5]||(c[5]=s(` Every card the learner has met, most painful first (time sunk × failures), with its pending review and current card ELO. `)),t(u,{size:`x-small`,color:`error`},{default:e(()=>c[3]||(c[3]=[s(`mdi-sync-alert`)])),_:1}),c[6]||(c[6]=s(` is a failed card holding an overdue review; `)),t(u,{size:`x-small`,color:`warning`},{default:e(()=>c[4]||(c[4]=[s(`mdi-snowflake`)])),_:1}),c[7]||(c[7]=s(` is a repeatedly failed card whose ELO has fewer updates than failures. `))]),t(v,{dense:``,class:`mb-2`},{default:e(()=>[(n(!0),f(p,null,l(E.value,i=>(n(),y(h,{key:i.label,cols:`6`,sm:`4`,md:`2`},{default:e(()=>[t(m,{variant:`tonal`,color:i.color,class:`pa-2 text-center`},{default:e(()=>[d(`div`,G,r(i.value),1),d(`div`,K,r(i.label),1)]),_:2},1032,[`color`])]),_:2},1024))),128))]),_:1}),d(`div`,q,[t(k,{modelValue:x.value,"onUpdate:modelValue":c[0]||(c[0]=e=>x.value=e),density:`compact`,color:`primary`,variant:`outlined`},{default:e(()=>[t(O,{value:`all`,size:`small`},{default:e(()=>[s(`All (`+r(_.value.length)+`)`,1)]),_:1}),t(O,{value:`stuck`,size:`small`},{default:e(()=>[t(u,{start:``,size:`small`,color:`error`},{default:e(()=>c[8]||(c[8]=[s(`mdi-sync-alert`)])),_:1}),s(` Stuck (`+r(T.value.stuck)+`) `,1)]),_:1}),t(O,{value:`failed`,size:`small`},{default:e(()=>[s(`Ever failed (`+r(T.value.failed)+`)`,1)]),_:1}),t(O,{value:`frozen`,size:`small`},{default:e(()=>[t(u,{start:``,size:`small`,color:`warning`},{default:e(()=>c[9]||(c[9]=[s(`mdi-snowflake`)])),_:1}),s(` Frozen ELO (`+r(T.value.frozen)+`) `,1)]),_:1})]),_:1},8,[`modelValue`]),t(A,{modelValue:S.value,"onUpdate:modelValue":c[1]||(c[1]=e=>S.value=e),density:`compact`,variant:`outlined`,"hide-details":``,clearable:``,placeholder:`filter by card / tag / type / content`,"prepend-inner-icon":`mdi-magnify`,style:{"max-width":`320px`}},null,8,[`modelValue`])]),_.value.length===0?(n(),y(j,{key:0,type:`info`,variant:`tonal`},{default:e(()=>c[10]||(c[10]=[s(`No card history for this learner.`)])),_:1})):(n(),y(L,{key:1,modelValue:C.value,"onUpdate:modelValue":c[2]||(c[2]=e=>C.value=e),multiple:``,variant:`accordion`},{default:e(()=>[(n(!0),f(p,null,l(D.value,i=>(n(),y(I,{key:i.cardId,value:i.cardId,"data-card":i.cardId,class:a(i.cardId===w.value?`sk-card-flash`:``)},{default:e(()=>[t(P,null,{default:e(()=>[d(`div`,J,[i.stuck?(n(),y(u,{key:0,color:`error`,size:`small`,title:`failed + overdue review`},{default:e(()=>c[11]||(c[11]=[s(`mdi-sync-alert`)])),_:1})):b(``,!0),i.frozenElo?(n(),y(u,{key:1,color:`warning`,size:`small`,title:`repeatedly failed, ELO barely updated`},{default:e(()=>c[12]||(c[12]=[s(` mdi-snowflake `)])),_:1})):b(``,!0),d(`span`,Y,r(i.card?.questionType??`card`),1),d(`code`,X,r(g(shortId)(i.cardId,24)),1),headline(i)?(n(),f(`span`,Z,r(headline(i)),1)):b(``,!0),t(M),i.fails>0?(n(),y(N,{key:3,size:`x-small`,color:`error`,variant:`tonal`},{default:e(()=>[s(r(i.fails)+` fail`+r(i.fails===1?``:`s`),1)]),_:2},1024)):b(``,!0),t(N,{size:`x-small`,variant:`tonal`},{default:e(()=>[s(r(i.attempts)+` view`+r(i.attempts===1?``:`s`),1)]),_:2},1024),t(N,{size:`x-small`,variant:`tonal`,color:`grey`},{default:e(()=>[s(r(g(fmtDuration)(i.totalTimeMs/1e3)),1)]),_:2},1024),i.pendingReview?(n(),y(N,{key:4,size:`x-small`,color:i.pendingReview.overdue?`error`:`success`,variant:`flat`},{default:e(()=>[s(` review `+r(i.pendingReview.overdue?`overdue`:`scheduled`),1)]),_:2},1032,[`color`])):b(``,!0),t(N,{size:`x-small`,variant:`tonal`,color:i.frozenElo?`warning`:void 0},{default:e(()=>[s(` ELO `+r(i.cardElo===null?`?`:Math.round(i.cardElo))+` `,1),i.cardEloCount===null?b(``,!0):(n(),f(`span`,Q,`/`+r(i.cardEloCount),1))]),_:2},1032,[`color`])])]),_:2},1024),t(F,null,{default:e(()=>[t(U,{dossier:i,interpreters:o.interpreters},null,8,[`dossier`,`interpreters`])]),_:2},1024)]),_:2},1032,[`value`,`data-card`,`class`]))),128))]),_:1},8,[`modelValue`]))])}}}),[[`__scopeId`,`data-v-bb6b302b`]]),re={class:`sk-run-detail`},ie={key:0,class:`mb-2`},ae={class:`text-right`},oe={class:`text-right`},se={class:`text-right`},ce={class:`text-right`},le={key:1,class:`mb-2`},ue={class:`text-right`},de={class:`text-right`},fe={class:`text-right`},pe={key:2,class:`mb-2 sk-mini-line text-medium-emphasis`},me={key:3,class:`mb-2`},he={key:4,class:`mb-2`},ge={class:`text-caption font-weight-medium`},_e={key:0,class:`text-medium-emphasis font-weight-regular`},ve={key:1,title:`runner-up`},ye=[`onClick`],be={class:`text-right`},xe={class:`text-caption font-weight-medium`},Se=[`onClick`],Ce={class:`text-medium-emphasis`},we={class:`text-no-wrap`},Te={class:`text-no-wrap`},Ee={class:`text-right text-no-wrap`},De={class:`text-caption`},Oe={key:5,class:`mb-2`},ke={class:`sk-hint-block`},Ae={key:6,class:`text-caption text-medium-emphasis`},je={key:2},Me=H(c({__name:`RunDetail`,props:{run:{}},emits:[`open-card`],setup(o,{emit:c}){let u=o,m=c,_=h(()=>{let e=u.run.unselectedNew,t=[];return e?.nextInLine&&t.push({label:`next new card in line`,card:e.nextInLine}),e?.topGenerated&&t.push({label:`top-generated new card (sunk)`,card:e.topGenerated}),t}),v=h(()=>selectedBySource(u.run).map(e=>`${e.source} ${e.count}`).join(` · `));return(o,c)=>{let u=i(`v-table`),h=i(`v-icon`);return n(),f(`div`,re,[o.run.generators?.length?(n(),f(`div`,ie,[c[1]||(c[1]=d(`div`,{class:`text-caption font-weight-medium`},`generators`,-1)),t(u,{density:`compact`,class:`sk-mini-table`},{default:e(()=>[c[0]||(c[0]=d(`thead`,null,[d(`tr`,null,[d(`th`),d(`th`,{class:`text-right`},`cards`),d(`th`,{class:`text-right`},`new`),d(`th`,{class:`text-right`},`review`),d(`th`,{class:`text-right`},`top`)])],-1)),d(`tbody`,null,[(n(!0),f(p,null,l(o.run.generators,e=>(n(),f(`tr`,{key:e.name},[d(`td`,null,r(e.name),1),d(`td`,ae,r(e.cardCount),1),d(`td`,oe,r(e.newCount),1),d(`td`,se,r(e.reviewCount),1),d(`td`,ce,r(e.topScore.toFixed(2)),1)]))),128))])]),_:1})])):b(``,!0),o.run.filters?.length?(n(),f(`div`,le,[c[3]||(c[3]=d(`div`,{class:`text-caption font-weight-medium`},`filters`,-1)),t(u,{density:`compact`,class:`sk-mini-table`},{default:e(()=>[c[2]||(c[2]=d(`thead`,null,[d(`tr`,null,[d(`th`),d(`th`,null,`kind`),d(`th`,{class:`text-right`},`boosted`),d(`th`,{class:`text-right`},`penalized`),d(`th`,{class:`text-right`},`passed`),d(`th`,{class:`text-right`},`removed`)])],-1)),d(`tbody`,null,[(n(!0),f(p,null,l(o.run.filters,e=>(n(),f(`tr`,{key:e.name},[d(`td`,null,r(e.name),1),d(`td`,null,r(e.kind??`—`),1),d(`td`,ue,r(e.boosted),1),d(`td`,de,r(e.penalized),1),d(`td`,fe,r(e.passed),1),d(`td`,{class:a([`text-right`,e.removed>0?`text-error`:``])},r(e.removed),3)]))),128))])]),_:1})])):b(``,!0),o.run.versions?(n(),f(`div`,pe,` strategies `+r(o.run.versions.strategies??`—`)+` · content `+r(o.run.versions.content??`—`),1)):b(``,!0),o.run.regulators?.length?(n(),f(`div`,me,[c[4]||(c[4]=d(`div`,{class:`text-caption font-weight-medium`},`regulators`,-1)),(n(!0),f(p,null,l(o.run.regulators,e=>(n(),f(`div`,{key:e.name,class:`sk-mini-line`},[d(`span`,{class:a(e.multiplier>1?`text-warning`:`text-medium-emphasis`)},` ×`+r(e.multiplier.toFixed(2)),3),s(` `+r(g(regulatorText)(e)),1)]))),128))])):b(``,!0),o.run.cards?.length?(n(),f(`div`,he,[d(`div`,ge,[c[5]||(c[5]=s(` selection `)),v.value?(n(),f(`span`,_e,` · by source: `+r(v.value),1)):b(``,!0)]),t(u,{density:`compact`,class:`sk-mini-table`},{default:e(()=>[c[7]||(c[7]=d(`thead`,null,[d(`tr`,null,[d(`th`),d(`th`,null,`card`),d(`th`,null,`origin`),d(`th`,null,`source`),d(`th`,{class:`text-right`},`score`)])],-1)),d(`tbody`,null,[(n(!0),f(p,null,l(o.run.cards,t=>(n(),f(`tr`,{key:t.cardId,class:a(t.selected?``:`text-medium-emphasis`)},[d(`td`,null,[t.selected?(n(),y(h,{key:0,size:`x-small`,color:`success`},{default:e(()=>c[6]||(c[6]=[s(`mdi-check`)])),_:1})):(n(),f(`span`,ve,`·`))]),d(`td`,null,[d(`a`,{class:`sk-card-link`,onClick:e=>m(`open-card`,t.cardId)},r(t.cardId),9,ye)]),d(`td`,null,r(t.origin),1),d(`td`,null,r(g(runCardSource)(t)),1),d(`td`,be,r(g(fmtScore)(t.score)),1)],2))),128))])]),_:1})])):b(``,!0),(n(!0),f(p,null,l(_.value,i=>(n(),f(`div`,{key:i.label,class:`mb-2`},[d(`div`,xe,[s(r(i.label)+`: `,1),d(`a`,{class:`sk-card-link`,onClick:e=>m(`open-card`,i.card.cardId)},r(i.card.cardId),9,Se),d(`span`,Ce,` (`+r(i.card.origin)+`, `+r(g(runCardSource)(i.card))+`) final `+r(g(fmtScore)(i.card.score)),1)]),t(u,{density:`compact`,class:`sk-mini-table`},{default:e(()=>[d(`tbody`,null,[(n(!0),f(p,null,l(i.card.trail,(e,t)=>(n(),f(`tr`,{key:t},[d(`td`,we,r(e.action),1),d(`td`,Te,r(e.strategyName),1),d(`td`,Ee,r(g(fmtScore)(e.score)),1),d(`td`,De,r(e.reason),1)]))),128))])]),_:2},1024)]))),128)),o.run.hints?(n(),f(`div`,Oe,[c[8]||(c[8]=d(`div`,{class:`text-caption font-weight-medium`},`hints`,-1)),d(`pre`,ke,r(JSON.stringify(o.run.hints,null,2)),1)])):b(``,!0),o.run.discardedTail?(n(),f(`div`,Ae,[s(` discarded tail: `+r(o.run.discardedTail.count)+` cards `,1),o.run.discardedTail.scoreRange?(n(),f(p,{key:0},[s(` · score [`+r(o.run.discardedTail.scoreRange[0].toFixed(2))+`, `+r(o.run.discardedTail.scoreRange[1].toFixed(2))+`] `,1)],64)):b(``,!0),o.run.discardedTail.eloRange?(n(),f(p,{key:1},[s(` · ELO [`+r(Math.round(o.run.discardedTail.eloRange[0]))+`, `+r(Math.round(o.run.discardedTail.eloRange[1]))+`] `,1)],64)):b(``,!0),o.run.discardedTail.note?(n(),f(`div`,je,r(o.run.discardedTail.note),1)):b(``,!0)])):b(``,!0)])}}}),[[`__scopeId`,`data-v-90c88783`]]),Ne={class:`d-flex align-center flex-wrap mb-4 ga-2`},Pe={class:`text-caption text-medium-emphasis`},Fe={class:`text-right`},Ie={class:`text-right`},Le={key:1,class:`text-caption text-disabled`},Re={class:`sk-hint-block`},ze={class:`sk-hint-block`},Be={class:`text-caption text-medium-emphasis mb-4`},Ve={class:`text-right`},He={class:`text-right`},Ue={class:`text-disabled`},We={class:`text-right`},Ge={class:`d-flex flex-wrap ga-5`},Ke={class:`text-caption text-medium-emphasis`},qe={class:`text-h6 text-success`},Je={class:`text-caption text-medium-emphasis`},Ye={class:`text-h6 text-error`},Xe={class:`text-h6`},Ze={class:`text-caption text-disabled`},Qe={class:`d-flex align-center flex-wrap mb-2 ga-3`},$e={key:4,class:`sk-timeline`},et={class:`sk-tl-time text-caption text-disabled`},tt={class:`sk-tl-gutter`},nt={key:0,class:`sk-tl-body`},rt={class:`d-flex align-center flex-wrap ga-1`},it={class:`font-weight-medium`},at={class:`text-caption text-medium-emphasis ml-2`},ot={key:1,class:`text-caption text-error ml-2`},st={key:1,class:`sk-tl-body`},ct=[`title`,`onClick`],lt={class:`text-caption`},ut={class:`text-caption text-medium-emphasis ml-2`},dt={key:0,class:`text-caption text-disabled ml-2`},ft=H(c({__name:`LearnerSessionDetail`,props:{dataset:{},sessionId:{},interpreters:{}},emits:[`open-card`],setup(o,{emit:c}){let u=o,m=c,_=h(()=>sessionDetail(u.dataset,u.sessionId,u.interpreters)),x=h(()=>_.value.summary.doc),S=h(()=>servedTags(_.value?.timeline??[],u.interpreters)),C=h(()=>eloLedger(_.value?.timeline??[])),w=h(()=>_.value?.timeline.filter(e=>e.kind===`response`).length??0),T=v(`all`),D=h(()=>{let e=_.value?.timeline??[];return!T.value||T.value===`all`?e:e.filter(e=>e.kind===T.value)}),O=v(new Set);function toggle(e){let t=new Set(O.value);t.has(e)?t.delete(e):t.add(e),O.value=t}let{copied:k,copy:A}=useCopy();function asText(){return _.value?sessionText(u.dataset.username,_.value,{servedTags:S.value,eloLedger:C.value},u.interpreters):``}let j=h(()=>{let e=_.value?.summary;if(!e)return``;let t=fmtDuration(e.doc.plannedSeconds);return e.durationSeconds===null?`— of ${t}`:`${fmtDuration(e.durationSeconds)} of ${t}`});function skillTags(e){return e.filter(e=>isSkillTag(u.interpreters,e)).slice(0,3)}function fmtNum(e){return e===null?`—`:Number.isInteger(e)?String(e):e.toFixed(1)}function fmtHints(e){return e==null?`none`:JSON.stringify(e,null,2)}function entryIcon(e){return e.kind===`run`?`mdi-cog-refresh-outline`:e.isCorrect===!0?`mdi-check-circle-outline`:e.isCorrect===!1?`mdi-close-circle-outline`:`mdi-circle-small`}function entryColor(e){return e.kind===`run`?`primary`:e.isCorrect===!0?`success`:e.isCorrect===!1?`error`:`grey`}function rowClass(e){return e.kind===`run`?`sk-tl-run`:e.isCorrect===!1?`sk-tl-fail`:``}return(o,c)=>{let u=i(`v-alert`),h=i(`v-chip`),v=i(`v-icon`),M=i(`v-spacer`),P=i(`v-btn`),F=i(`v-table`),I=i(`v-card`),L=i(`v-col`),R=i(`v-row`),z=i(`v-btn-toggle`);return n(),f(`div`,null,[_.value?(n(),f(p,{key:1},[d(`div`,Ne,[t(h,{size:`small`,variant:`flat`,color:g(statusColor)(x.value.status)},{default:e(()=>[s(r(x.value.status),1)]),_:1},8,[`color`]),t(h,{size:`small`,variant:`tonal`},{default:e(()=>[s(r(g(fmtTime)(x.value.startTime)),1)]),_:1}),t(h,{size:`small`,variant:`tonal`,color:`grey`},{default:e(()=>[s(r(j.value),1)]),_:1}),(n(!0),f(p,null,l(_.value.summary.flags,i=>(n(),y(h,{key:i,size:`small`,variant:`tonal`,color:g(N)[i].color,title:g(E)[i].help},{default:e(()=>[t(v,{start:``,size:`small`},{default:e(()=>[s(r(g(N)[i].icon),1)]),_:2},1024),s(` `+r(g(E)[i].label),1)]),_:2},1032,[`color`,`title`]))),128)),t(M),d(`code`,Pe,r(o.sessionId),1),t(P,{variant:`text`,size:`small`,"prepend-icon":g(k)===`session`?`mdi-check`:`mdi-clipboard-text-outline`,color:g(k)===`session`?`success`:void 0,onClick:c[0]||(c[0]=e=>g(A)(asText(),`session`))},{default:e(()=>[s(r(g(k)===`session`?`Copied`:`Copy as text`),1)]),_:1},8,[`prepend-icon`,`color`])]),_.value.responsesMissing?(n(),y(u,{key:0,type:`warning`,variant:`tonal`,density:`compact`,class:`mb-4`},{default:e(()=>[s(` The session records `+r(x.value.tally?.responses)+` responses but only `+r(w.value)+` card records carry its id. The timeline is incomplete. `,1)]),_:1})):b(``,!0),t(R,{class:`mb-2`},{default:e(()=>[t(L,{cols:`12`,md:`6`},{default:e(()=>[t(I,{variant:`outlined`,class:`pa-3 h-100`},{default:e(()=>[c[4]||(c[4]=d(`div`,{class:`text-subtitle-2 mb-1`},`Learner state`,-1)),c[5]||(c[5]=d(`div`,{class:`text-caption text-medium-emphasis mb-3`},` What the navigator was choosing against, and what moved. `,-1)),_.value.summary.state.length?(n(),y(F,{key:0,density:`compact`,class:`sk-mini-table`},{default:e(()=>[c[3]||(c[3]=d(`thead`,null,[d(`tr`,null,[d(`th`),d(`th`,{class:`text-right`},`Start`),d(`th`,{class:`text-right`},`End`),d(`th`,{class:`text-right`},`Δ`)])],-1)),d(`tbody`,null,[(n(!0),f(p,null,l(_.value.summary.state,e=>(n(),f(`tr`,{key:e.label},[d(`td`,null,r(e.label),1),d(`td`,Fe,r(fmtNum(e.from)),1),d(`td`,Ie,r(fmtNum(e.to)),1),d(`td`,{class:a([`text-right`,g(deltaClass)(e.delta)])},r(g(fmtDelta)(e.delta)),3)]))),128))])]),_:1})):(n(),f(`div`,Le,`No state snapshot recorded.`))]),_:1})]),_:1}),t(L,{cols:`12`,md:`6`},{default:e(()=>[t(I,{variant:`outlined`,class:`pa-3 h-100`},{default:e(()=>[c[6]||(c[6]=d(`div`,{class:`text-subtitle-2 mb-1`},`Session hints`,-1)),c[7]||(c[7]=d(`div`,{class:`text-caption text-medium-emphasis mb-3`},` What outcome observers told the navigator. They act only through these. `,-1)),c[8]||(c[8]=d(`span`,{class:`text-caption font-weight-medium`},`at open`,-1)),d(`pre`,Re,r(fmtHints(x.value.config?.initHints)),1),c[9]||(c[9]=d(`span`,{class:`text-caption font-weight-medium`},`at close`,-1)),d(`pre`,ze,r(fmtHints(x.value.finalHints)),1)]),_:1})]),_:1})]),_:1}),d(`div`,Be,[s(` batch limit `+r(x.value.config?.defaultBatchLimit??`?`)+` · `+r(x.value.config?.sourceCount??`?`)+` source(s) · opening queues supply `+r(x.value.initialQueues?.supplyQ??`?`)+` / failed `+r(x.value.initialQueues?.failedQ??`?`)+` `,1),x.value.tally?(n(),f(p,{key:0},[s(` · ended with `+r(x.value.tally.failedQRemaining)+` still in the failed queue`,1)],64)):b(``,!0),x.value.versions?(n(),f(p,{key:1},[s(` · framework `+r(x.value.versions.framework),1),x.value.versions.app?(n(),f(p,{key:0},[s(` · app `+r(x.value.versions.app),1)],64)):b(``,!0)],64)):b(``,!0)]),S.value.length?(n(),y(I,{key:1,variant:`outlined`,class:`pa-3 mb-4`},{default:e(()=>[c[11]||(c[11]=d(`div`,{class:`text-subtitle-2 mb-1`},`Served tags`,-1)),c[12]||(c[12]=d(`div`,{class:`text-caption text-medium-emphasis mb-2`},` What this sitting put in front of the learner, by content tag. A response with several tags counts toward each. `,-1)),t(F,{density:`compact`,class:`sk-mini-table`},{default:e(()=>[c[10]||(c[10]=d(`thead`,null,[d(`tr`,null,[d(`th`,null,`Tag`),d(`th`,{class:`text-right`},`Resp.`),d(`th`,{class:`text-right`},`Cards`),d(`th`,{class:`text-right`},`Accuracy`),d(`th`,{class:`text-right`},`Time`)])],-1)),d(`tbody`,null,[(n(!0),f(p,null,l(S.value,e=>(n(),f(`tr`,{key:e.tag},[d(`td`,null,[d(`code`,{class:a(g(isSkillTag)(o.interpreters,e.tag)?`text-primary`:``)},r(e.tag),3)]),d(`td`,Ve,r(e.responses),1),d(`td`,He,r(e.cards),1),d(`td`,{class:a([`text-right`,g(accuracyClass)(e.accuracy)])},[e.accuracy===null?(n(),f(p,{key:0},[s(`—`)],64)):(n(),f(p,{key:1},[s(r(Math.round(e.accuracy*100))+`% `,1),d(`span`,Ue,`(`+r(e.correct)+`/`+r(e.correct+e.incorrect)+`)`,1)],64))],2),d(`td`,We,r((e.totalTimeMs/1e3).toFixed(1))+`s`,1)]))),128))])]),_:1})]),_:1})):b(``,!0),C.value?(n(),y(I,{key:2,variant:`outlined`,class:`pa-3 mb-4`},{default:e(()=>[c[15]||(c[15]=d(`div`,{class:`text-subtitle-2 mb-1`},`ELO ledger`,-1)),c[16]||(c[16]=d(`div`,{class:`text-caption text-medium-emphasis mb-3`},` The per-response learner global-ELO exchanges that net to the session's ELO move. Wins above the learner's level pay little; losses below it cost a lot, so a high hit rate can still net negative. `,-1)),d(`div`,Ge,[d(`div`,null,[c[13]||(c[13]=d(`div`,{class:`text-caption text-medium-emphasis`},`net`,-1)),d(`div`,{class:a([`text-h6`,g(deltaClass)(C.value.net)])},r(g(fmtDelta)(C.value.net)),3)]),d(`div`,null,[d(`div`,Ke,`gained · `+r(C.value.wins)+` win(s)`,1),d(`div`,qe,r(g(fmtDelta)(C.value.gained)),1)]),d(`div`,null,[d(`div`,Je,`lost · `+r(C.value.losses)+` loss(es)`,1),d(`div`,Ye,r(g(fmtDelta)(C.value.lost)),1)]),d(`div`,null,[c[14]||(c[14]=d(`div`,{class:`text-caption text-medium-emphasis`},`exchanges`,-1)),d(`div`,Xe,r(C.value.count),1),d(`div`,Ze,`of `+r(w.value)+` response(s)`,1)])])]),_:1})):b(``,!0),d(`div`,Qe,[c[17]||(c[17]=d(`h2`,{class:`text-h6`},`Timeline`,-1)),t(z,{modelValue:T.value,"onUpdate:modelValue":c[1]||(c[1]=e=>T.value=e),density:`compact`,color:`primary`,variant:`outlined`},{default:e(()=>[t(P,{value:`all`,size:`small`},{default:e(()=>[s(`All (`+r(_.value.timeline.length)+`)`,1)]),_:1}),t(P,{value:`response`,size:`small`},{default:e(()=>[s(`Responses (`+r(w.value)+`)`,1)]),_:1}),t(P,{value:`run`,size:`small`},{default:e(()=>[s(`Runs (`+r(_.value.timeline.length-w.value)+`)`,1)]),_:1})]),_:1},8,[`modelValue`])]),_.value.timeline.length===0?(n(),y(u,{key:3,type:`info`,variant:`tonal`},{default:e(()=>c[18]||(c[18]=[s(`Nothing recorded for this session.`)])),_:1})):(n(),f(`div`,$e,[(n(!0),f(p,null,l(D.value,(i,u)=>(n(),f(`div`,{key:u,class:a([`sk-tl-row`,rowClass(i)])},[d(`div`,et,r(g(fmtClock)(i.at)),1),d(`div`,tt,[t(v,{size:`small`,color:entryColor(i)},{default:e(()=>[s(r(entryIcon(i)),1)]),_:2},1032,[`color`])]),i.kind===`run`?(n(),f(`div`,nt,[d(`div`,rt,[d(`span`,it,r(i.run.label),1),i.run.mode?(n(),y(h,{key:0,size:`x-small`,variant:`tonal`},{default:e(()=>[s(r(i.run.mode),1)]),_:2},1024)):b(``,!0),d(`span`,at,` generated `+r(i.run.generatedCount)+` → selected `+r(i.run.finalCount)+` (`+r(i.run.newSelected)+` new, `+r(i.run.reviewsSelected)+` review) `,1),i.run.generatedCount>0&&i.run.finalCount===0?(n(),f(`span`,ot,` nothing survived `)):b(``,!0),typeof i.run.userElo==`number`?(n(),y(h,{key:2,size:`x-small`,variant:`tonal`,color:`grey`,class:`ml-2`},{default:e(()=>[s(` ELO `+r(Math.round(i.run.userElo)),1)]),_:2},1024)):b(``,!0),t(M),t(P,{icon:O.value.has(i.run.runId)?`mdi-chevron-up`:`mdi-chevron-down`,size:`x-small`,variant:`text`,onClick:e=>toggle(i.run.runId)},null,8,[`icon`,`onClick`]),t(P,{icon:g(k)===i.run.runId?`mdi-check`:`mdi-content-copy`,size:`x-small`,variant:`text`,color:g(k)===i.run.runId?`success`:void 0,title:`Copy run as text`,onClick:e=>g(A)(g(runText)(i.run),i.run.runId)},null,8,[`icon`,`color`,`onClick`])]),O.value.has(i.run.runId)?(n(),y(Me,{key:0,run:i.run,class:`mt-1`,onOpenCard:c[2]||(c[2]=e=>m(`open-card`,e))},null,8,[`run`])):b(``,!0)])):(n(),f(`div`,st,[d(`a`,{class:`sk-card-link`,title:`Open ${i.cardId} in card history`,onClick:e=>m(`open-card`,i.cardId)},[s(r(i.questionType??`card`)+` `,1),d(`code`,lt,r(g(shortId)(i.cardId)),1)],8,ct),(n(!0),f(p,null,l(skillTags(i.tags),t=>(n(),y(h,{key:t,size:`x-small`,variant:`outlined`,color:`primary`,class:`ml-1`},{default:e(()=>[s(r(g(shortTag)(o.interpreters,t)),1)]),_:2},1024))),128)),d(`span`,ut,[s(r((i.timeSpentMs/1e3).toFixed(1))+`s `,1),i.priorAttempts?(n(),f(p,{key:0},[s(` · attempt `+r(i.priorAttempts+1),1)],64)):b(``,!0)]),i.userAnswer==null?b(``,!0):(n(),f(`span`,dt,`“`+r(g(fmtAnswer)(i.userAnswer))+`”`,1)),i.elo?(n(),f(p,{key:1},[t(h,{size:`x-small`,variant:`tonal`,color:g(deltaColor)(i.elo.global.delta),class:`ml-2`,title:`learner global ELO ${i.elo.global.before} → ${i.elo.global.after} · userScore ${i.elo.userScore.toFixed(2)}`},{default:e(()=>[s(` ELO `+r(g(fmtDelta)(i.elo.global.delta)),1)]),_:2},1032,[`color`,`title`]),(n(!0),f(p,null,l(g(scoredTagDeltas)(i.elo),t=>(n(),y(h,{key:t.tag,size:`x-small`,variant:`text`,color:g(deltaColor)(t.delta),class:`sk-elo-tag`,title:`${t.tag}: ${t.before} → ${t.after} (score ${t.score?.toFixed(2)})`},{default:e(()=>[s(r(g(shortTag)(o.interpreters,t.tag))+` `+r(g(fmtDelta)(t.delta)),1)]),_:2},1032,[`color`,`title`]))),128))],64)):b(``,!0)]))],2))),128))]))],64)):(n(),y(u,{key:0,type:`info`,variant:`tonal`},{default:e(()=>[s(`No session with id `+r(o.sessionId)+`.`,1)]),_:1}))])}}}),[[`__scopeId`,`data-v-3cc6eb88`]]),pt={class:`text-h6`},mt={class:`text-caption`},ht={class:`d-flex align-center flex-wrap mb-3 ga-3`},gt=[`onClick`],_t={class:`text-no-wrap`},vt={class:`text-right`},yt={class:`text-right`},bt={key:1,class:`text-disabled`},xt={class:`text-right`},St={class:`text-no-wrap text-caption`},Ct={class:`text-no-wrap text-caption`},wt={key:0},Tt={key:0,class:`text-disabled`},Et={class:`text-right`},Dt=H(c({__name:`LearnerSessionList`,props:{dataset:{},interpreters:{}},emits:[`open`],setup(o,{emit:c}){let u=o,m=c,_=h(()=>summarizeSessions(u.dataset,u.interpreters)),x=v(`all`),S=h(()=>{let e=new Map;for(let t of _.value)for(let n of t.flags)e.set(n,(e.get(n)??0)+1);return[...e.entries()].map(([e,t])=>({flag:e,count:t})).sort((e,t)=>t.count-e.count)}),C=h(()=>!x.value||x.value===`all`?_.value:_.value.filter(e=>e.flags.includes(x.value))),w=h(()=>{let e=_.value,t=e.filter(e=>e.doc.status===`closed`).length,n=e.reduce((e,t)=>e+(t.doc.tally?.responses??0),0),r=e.reduce((e,t)=>e+(t.doc.tally?.correct??0),0),i=e.reduce((e,t)=>e+(t.durationSeconds??0),0);return[{label:`sessions`,value:e.length,color:`primary`},{label:`completed`,value:t,color:`success`},{label:`not completed`,value:e.length-t,color:`error`},{label:`responses`,value:n,color:`primary`},{label:`overall acc.`,value:n>0?`${Math.round(r/n*100)}%`:`—`,color:`primary`},{label:`time studied`,value:fmtDuration(i),color:`grey`}]});function deltas(e){let t=[];e.eloNet!==null&&t.push({label:`elo`,delta:Math.round(e.eloNet)});for(let n of u.interpreters?.progressMetrics??[]){let r=e.state.find(e=>e.label===n);r&&t.push({label:n,delta:r.delta})}return t}function clockText(e){let t=fmtDuration(e.doc.plannedSeconds);return e.durationSeconds===null?`— of ${t}`:`${fmtDuration(e.durationSeconds)} of ${t}`}return(o,c)=>{let u=i(`v-card`),h=i(`v-col`),v=i(`v-row`),T=i(`v-btn`),D=i(`v-icon`),O=i(`v-btn-toggle`),k=i(`v-alert`),A=i(`v-chip`),j=i(`v-table`);return n(),f(`div`,null,[c[4]||(c[4]=d(`p`,{class:`text-caption text-medium-emphasis mb-4`},[s(` One row per sitting. Flags name a specific way the session failed to do its job; open one to read its interleaved timeline of responses and pipeline runs. `),d(`strong`,null,`Δ`),s(` is movement across the session: ELO, then any progress metrics the course declares. `)],-1)),t(v,{dense:``,class:`mb-2`},{default:e(()=>[(n(!0),f(p,null,l(w.value,i=>(n(),y(h,{key:i.label,cols:`6`,sm:`4`,md:`2`},{default:e(()=>[t(u,{variant:`tonal`,color:i.color,class:`pa-2 text-center`},{default:e(()=>[d(`div`,pt,r(i.value),1),d(`div`,mt,r(i.label),1)]),_:2},1032,[`color`])]),_:2},1024))),128))]),_:1}),d(`div`,ht,[t(O,{modelValue:x.value,"onUpdate:modelValue":c[0]||(c[0]=e=>x.value=e),density:`compact`,color:`primary`,variant:`outlined`},{default:e(()=>[t(T,{value:`all`,size:`small`},{default:e(()=>[s(`All (`+r(_.value.length)+`)`,1)]),_:1}),(n(!0),f(p,null,l(S.value,i=>(n(),y(T,{key:i.flag,value:i.flag,size:`small`,title:g(E)[i.flag].help},{default:e(()=>[t(D,{start:``,size:`small`,color:g(N)[i.flag].color},{default:e(()=>[s(r(g(N)[i.flag].icon),1)]),_:2},1032,[`color`]),s(` `+r(g(E)[i.flag].label)+` (`+r(i.count)+`) `,1)]),_:2},1032,[`value`,`title`]))),128))]),_:1},8,[`modelValue`])]),_.value.length===0?(n(),y(k,{key:0,type:`info`,variant:`tonal`},{default:e(()=>c[1]||(c[1]=[s(` No study sessions recorded. Session records began with a framework release; there is no backfill, so earlier activity shows only in card history. `)])),_:1})):(n(),y(j,{key:1,density:`compact`,class:`sk-admin-table`},{default:e(()=>[c[3]||(c[3]=d(`thead`,null,[d(`tr`,null,[d(`th`,null,`Started`),d(`th`,null,`Status`),d(`th`,{class:`text-right`},`Cards`),d(`th`,{class:`text-right`},`Acc.`),d(`th`,{class:`text-right`},`Runs`),d(`th`,null,`Clock`),d(`th`,null,`Δ`),d(`th`,null,`Flags`),d(`th`)])],-1)),d(`tbody`,null,[(n(!0),f(p,null,l(C.value,i=>(n(),f(`tr`,{key:i.doc.sessionId,class:`sk-admin-row`,onClick:e=>m(`open`,i.doc.sessionId)},[d(`td`,_t,r(g(fmtTime)(i.doc.startTime)),1),d(`td`,null,[t(A,{size:`x-small`,variant:`flat`,color:g(statusColor)(i.doc.status)},{default:e(()=>[s(r(i.doc.status),1)]),_:2},1032,[`color`])]),d(`td`,vt,r(i.doc.tally?.cardsPresented??`—`),1),d(`td`,yt,[i.accuracy===null?(n(),f(`span`,bt,`—`)):(n(),f(`span`,{key:0,class:a(g(accuracyClass)(i.accuracy))},r(Math.round(i.accuracy*100))+`% `,3))]),d(`td`,xt,r(i.doc.runs?.length??0),1),d(`td`,St,r(clockText(i)),1),d(`td`,Ct,[(n(!0),f(p,null,l(deltas(i),(e,t)=>(n(),f(p,{key:e.label},[t>0?(n(),f(`span`,wt,` · `)):b(``,!0),d(`span`,{class:a(g(deltaClass)(e.delta))},r(g(fmtDelta)(e.delta))+`\xA0`+r(e.label),3)],64))),128)),deltas(i).length===0?(n(),f(`span`,Tt,`—`)):b(``,!0)]),d(`td`,null,[(n(!0),f(p,null,l(i.flags,t=>(n(),y(D,{key:t,size:`small`,class:`mr-1`,color:g(N)[t].color,title:`${g(E)[t].label}: ${g(E)[t].help}`},{default:e(()=>[s(r(g(N)[t].icon),1)]),_:2},1032,[`color`,`title`]))),128))]),d(`td`,Et,[t(D,{size:`small`,class:`text-disabled`},{default:e(()=>c[2]||(c[2]=[s(`mdi-chevron-right`)])),_:1})])],8,gt))),128))])]),_:1}))])}}}),[[`__scopeId`,`data-v-5c46cc58`]]),Ot={class:`sk-pipeline`},kt={class:`d-flex flex-wrap align-center ga-2 mb-3`},At={class:`text-caption`},jt={key:0,class:`text-caption text-medium-emphasis`},Mt={class:`sk-stage`},Nt={class:`d-flex align-center mb-1`},Pt={class:`sk-stage-num`},Ft={class:`font-weight-medium`},It={class:`text-caption text-medium-emphasis mb-2`},Lt={class:`d-flex flex-wrap align-center ga-2`},Rt={class:`font-weight-medium`},zt={class:`text-caption`},Bt={key:0,class:`text-caption mt-1`},Vt={key:1,class:`text-caption mt-1`},Ht={key:1,class:`text-medium-emphasis`},Ut={key:2,class:`mt-1`},Wt=[`onClick`],Gt={key:0,class:`sk-config`},Kt={key:0,class:`text-caption text-medium-emphasis`},qt={class:`d-flex flex-wrap align-center ga-2`},Jt={class:`font-weight-medium`},Yt={class:`text-caption`},Xt={key:0,class:`text-caption mt-1`},Zt={key:1,class:`text-caption mt-1 text-medium-emphasis`},Qt={key:2,class:`mt-1`},$t={class:`sk-impact-bar`},en=[`title`],$={class:`text-caption`},tn={key:1,class:`text-caption text-medium-emphasis`},nn={key:3,class:`mt-1`},rn=[`onClick`],an={key:0,class:`sk-config`},on={class:`sk-nav`},sn={class:`d-flex flex-wrap align-center ga-2`},cn={class:`text-caption mt-1`},ln={key:0,class:`text-caption mt-1`},un={class:`sk-nav`},dn={class:`d-flex flex-wrap align-center ga-2`},fn={class:`text-caption mt-1`},pn={key:0,class:`text-caption mt-1`},mn={key:0,class:`text-caption text-medium-emphasis`},hn={key:3,class:`text-caption`},gn={key:0,class:`sk-stage-arrow`},_n={key:0,class:`text-caption text-medium-emphasis mt-3`},vn=H(c({__name:`PipelineOverview`,props:{strategies:{},courseId:{},stats:{},statsLabel:{}},setup(o){let c=o,u={"strategy-doc":{label:`strategy doc`,color:`primary`},"assembler-default":{label:`added by the assembler`,color:`secondary`},"default-pipeline":{label:`default pipeline`,color:`warning`}},regStat=e=>c.stats?.regulators.find(t=>t.name===e);function regStatText(e){return`In these runs: active (×>1) in ${e.runsActive}/${e.runs}, mean ×${e.meanMultiplier.toFixed(2)}, max ×${e.maxMultiplier.toFixed(2)}. Last: ${regulatorText(e.last)}.`}let m={gate:`Gate: its penalties mean not ready yet; regulators will not lift what it penalized.`,signal:`Signal: its penalties express preference.`};function filterKind(e){let t=e.kind??filterStat(e.name)?.kind;return t?{kind:t,label:t,help:m[t]}:{kind:`gate`,label:`gate (undeclared)`,help:`${m.gate} Its class declares no kind, so it counts as a gate.`}}let _=h(()=>C(c.strategies,c.courseId)),x=h(()=>new Map((c.stats?.generators??[]).map(e=>[e.name,e]))),T=h(()=>new Map((c.stats?.filters??[]).map(e=>[e.name,e]))),genStat=e=>x.value.get(e),filterStat=e=>T.value.get(e),E=h(()=>{let e=[..._.value.notes],t=c.stats;if(!t)return e;for(let t of _.value.filters){let n=filterStat(t.name);n&&n.boosted+n.penalized+n.removed===0&&e.push(`${t.name} changed no candidate's score in ${n.runs} runs.`)}if(t.runsWithSelection>0)for(let t of _.value.generators){let n=genStat(t.name);n&&n.runs>0&&n.selected===0&&e.push(`${t.name} proposed candidates in ${n.runs} runs, and none was selected.`)}return e});function accuracyOf(e){return e.firstAttempts>0?e.firstAttemptsCorrect/e.firstAttempts:null}function impactParts(e){let t=e.boosted+e.penalized+e.passed+e.removed||1;return[{key:`boosted`,count:e.boosted,color:`success`},{key:`penalized`,count:e.penalized,color:`warning`},{key:`passed`,count:e.passed,color:`grey`},{key:`removed`,count:e.removed,color:`error`}].map(e=>({...e,share:e.count/t}))}function fmtNum(e){return e>=10?Math.round(e).toString():e.toFixed(1)}function fmtPct(e){return e===0?`0%`:e<.01?`<1%`:`${Math.round(e*100)}%`}let D=v(new Set);function toggleConfig(e){let t=new Set(D.value);t.has(e)?t.delete(e):t.add(e),D.value=t}function prettyConfig(e){if(!e)return``;try{let t=JSON.parse(e),n=JSON.stringify(t,null,2);return n===`{}`?``:n}catch{return e}}return(o,c)=>{let m=i(`v-chip`),h=i(`v-alert`),v=i(`v-icon`);return n(),f(`div`,Ot,[d(`div`,kt,[t(m,{size:`small`,variant:`tonal`,color:_.value.kind===`default`?`warning`:`primary`},{default:e(()=>[s(r(_.value.kind===`default`?`default pipeline: the course has no strategy docs`:`assembled from strategy docs`),1)]),_:1},8,[`color`]),d(`span`,At,r(_.value.generators.length)+` generator(s) · `+r(_.value.filters.length)+` filter(s) `,1),o.stats?(n(),f(`span`,jt,` · run stats`+r(o.statsLabel?` for ${o.statsLabel}`:``)+`: `+r(o.stats.runs)+` runs over `+r(o.stats.sessions)+` sessions, `+r(g(fmtTime)(o.stats.firstRunAt))+` – `+r(g(fmtTime)(o.stats.lastRunAt)),1)):b(``,!0)]),(n(!0),f(p,null,l(_.value.skipped,t=>(n(),y(h,{key:t.strategy._id,type:`warning`,variant:`tonal`,density:`compact`,class:`mb-2`},{default:e(()=>[d(`strong`,null,r(t.strategy.name),1),c[0]||(c[0]=s(` (`)),d(`code`,null,r(t.strategy.implementingClass),1),s(`) is `+r(t.reason)+` in this app, so it would not run here. A course's own navigators only plan correctly in the app that registers them. `,1)]),_:2},1024))),128)),(n(!0),f(p,null,l(_.value.warnings,t=>(n(),y(h,{key:t,type:`warning`,variant:`tonal`,density:`compact`,class:`mb-2`},{default:e(()=>[s(r(t),1)]),_:2},1024))),128)),(n(!0),f(p,null,l(E.value,t=>(n(),y(h,{key:t,type:`info`,variant:`tonal`,density:`compact`,class:`mb-2`},{default:e(()=>[s(r(t),1)]),_:2},1024))),128)),(n(!0),f(p,null,l(g(w),(i,h)=>(n(),f(`div`,{key:i.key},[d(`div`,Mt,[d(`div`,Nt,[d(`span`,Pt,r(h+1),1),d(`span`,Ft,r(i.title),1)]),d(`div`,It,r(i.summary),1),i.key===`generate`?(n(!0),f(p,{key:0},l(_.value.generators,i=>(n(),f(`div`,{key:i.name,class:`sk-nav`},[d(`div`,Lt,[d(`span`,Rt,r(i.name),1),d(`code`,zt,r(i.implementingClass),1),t(m,{size:`x-small`,variant:`outlined`,color:u[i.origin].color},{default:e(()=>[s(r(u[i.origin].label),1)]),_:2},1032,[`color`])]),i.strategy?.description?(n(),f(`div`,Bt,r(i.strategy.description),1)):b(``,!0),o.stats?(n(),f(`div`,Vt,[genStat(i.name)?(n(),f(p,{key:0},[s(r(fmtNum(genStat(i.name).meanCards))+` candidates/run (`+r(fmtNum(genStat(i.name).meanNew))+` new, `+r(fmtNum(genStat(i.name).meanReview))+` review) · top score `+r(genStat(i.name).topScoreLast.toFixed(2))+` last, `+r(genStat(i.name).topScoreMax.toFixed(2))+` max `,1),o.stats.runsWithSelection>0?(n(),f(p,{key:0},[c[1]||(c[1]=s(` · `)),d(`strong`,null,r(genStat(i.name).selected),1),c[2]||(c[2]=s(` selected `)),genStat(i.name).firstAttempts>0?(n(),f(p,{key:0},[s(` · first attempts `+r(genStat(i.name).firstAttemptsCorrect)+`/`+r(genStat(i.name).firstAttempts)+` correct `,1),d(`span`,{class:a(g(accuracyClass)(accuracyOf(genStat(i.name))))},` (`+r(Math.round(100*accuracyOf(genStat(i.name))))+`%) `,3)],64)):b(``,!0)],64)):b(``,!0)],64)):(n(),f(`span`,Ht,`absent from these runs`))])):b(``,!0),prettyConfig(i.strategy?.serializedData)?(n(),f(`div`,Ut,[d(`a`,{class:`sk-config-link text-caption`,onClick:e=>toggleConfig(`g:${i.name}`)},r(D.value.has(`g:${i.name}`)?`Hide`:`Show`)+` config `,9,Wt),D.value.has(`g:${i.name}`)?(n(),f(`pre`,Gt,r(prettyConfig(i.strategy?.serializedData)),1)):b(``,!0)])):b(``,!0)]))),128)):i.key===`filter`?(n(),f(p,{key:1},[_.value.filters.length===0?(n(),f(`div`,Kt,`No filters.`)):b(``,!0),(n(!0),f(p,null,l(_.value.filters,i=>(n(),f(`div`,{key:i.name,class:`sk-nav`},[d(`div`,qt,[d(`span`,Jt,r(i.name),1),d(`code`,Yt,r(i.implementingClass),1),t(m,{size:`x-small`,variant:`outlined`,color:u[i.origin].color},{default:e(()=>[s(r(u[i.origin].label),1)]),_:2},1032,[`color`]),i.strategy?.learnable?(n(),y(m,{key:0,size:`x-small`,variant:`outlined`},{default:e(()=>c[3]||(c[3]=[s(`learnable weight`)])),_:1})):b(``,!0),t(m,{size:`x-small`,variant:`tonal`,color:filterKind(i).kind===`gate`?`deep-orange`:`blue-grey`,title:filterKind(i).help},{default:e(()=>[s(r(filterKind(i).label),1)]),_:2},1032,[`color`,`title`])]),i.strategy?.description?(n(),f(`div`,Xt,r(i.strategy.description),1)):i.strategy?b(``,!0):(n(),f(`div`,Zt,` Built in code; no strategy document. `)),o.stats?(n(),f(`div`,Qt,[filterStat(i.name)?(n(),f(p,{key:0},[d(`div`,$t,[(n(!0),f(p,null,l(impactParts(filterStat(i.name)),e=>(n(),f(`div`,{key:e.key,class:a(`bg-${e.color}`),style:S({width:`${e.share*100}%`}),title:`${e.key}: ${e.count}`},null,14,en))),128))]),d(`div`,$,[s(` over `+r(filterStat(i.name).runs)+` runs: `,1),(n(!0),f(p,null,l(impactParts(filterStat(i.name)),e=>(n(),f(`span`,{key:e.key,class:`mr-2`},[d(`span`,{class:a(`text-${e.color}`)},`●`,2),s(` `+r(e.key)+` `+r(fmtPct(e.share)),1)]))),128))])],64)):(n(),f(`span`,tn,`absent from these runs`))])):b(``,!0),prettyConfig(i.strategy?.serializedData)?(n(),f(`div`,nn,[d(`a`,{class:`sk-config-link text-caption`,onClick:e=>toggleConfig(`f:${i.name}`)},r(D.value.has(`f:${i.name}`)?`Hide`:`Show`)+` config `,9,rn),D.value.has(`f:${i.name}`)?(n(),f(`pre`,an,r(prettyConfig(i.strategy?.serializedData)),1)):b(``,!0)])):b(``,!0)]))),128))],64)):i.key===`regulate`?(n(),f(p,{key:2},[d(`div`,on,[d(`div`,sn,[c[5]||(c[5]=d(`span`,{class:`font-weight-medium`},`Review mass`,-1)),t(m,{size:`x-small`,variant:`outlined`},{default:e(()=>c[4]||(c[4]=[s(`on review cards`)])),_:1})]),d(`div`,cn,` Each due review weighs its SRS urgency (0–1) times the filters' net effect on it. Above `+r(_.value.regulators.reviewMass.healthyMass)+` card-equivalents, every review is multiplied by ×`+r(_.value.regulators.reviewMass.rate)+` per `+r(_.value.regulators.reviewMass.healthyMass)+` in excess (uncapped). Reviews without an urgency weigh their score against `+r(_.value.regulators.reviewMass.referenceScore)+`. `,1),regStat(`review-mass`)?(n(),f(`div`,ln,r(regStatText(regStat(`review-mass`))),1)):b(``,!0)]),d(`div`,un,[d(`div`,dn,[c[7]||(c[7]=d(`span`,{class:`font-weight-medium`},`Intake`,-1)),t(m,{size:`x-small`,variant:`outlined`},{default:e(()=>c[6]||(c[6]=[s(`on new cards no gate penalized`)])),_:1})]),d(`div`,fn,` ×`+r(_.value.regulators.intake.rate)+` per `+r(_.value.regulators.intake.scaleHours)+` hours since a new card was last presented (uncapped). The clock stops while no eligible new card exists. `,1),regStat(`intake`)?(n(),f(`div`,pn,r(regStatText(regStat(`intake`))),1)):b(``,!0)]),o.stats&&o.stats.regulators.length===0?(n(),f(`div`,mn,` None of these runs recorded regulator readings (recorded from 0.2.29). `)):b(``,!0)],64)):i.key===`select`&&o.stats&&o.stats.runsWithSelection>0?(n(),f(`div`,hn,[s(r(o.stats.selectedUnattributed)+` selected card(s) had no generator: forced in by a hint's `,1),c[8]||(c[8]=d(`code`,null,`requireCards`,-1)),c[9]||(c[9]=s(`. `))])):b(``,!0)]),h<g(w).length-1?(n(),f(`div`,gn,[t(v,{size:`small`},{default:e(()=>c[10]||(c[10]=[s(`mdi-arrow-down`)])),_:1})])):b(``,!0)]))),128)),o.stats&&o.stats.runsWithSelection===0?(n(),f(`div`,_n,` None of these runs recorded which cards they selected (recorded from 0.2.28), so selection and first-attempt counts are not shown. `)):b(``,!0)])}}}),[[`__scopeId`,`data-v-24b6038f`]]),yn=c({__name:`LearnerDiagnostics`,props:{dataset:{},interpreters:{}},setup(a){let o=a,c=v(`sessions`),l=v(null),d=v(void 0),m=h(()=>pipelineRunStats(o.dataset));function openCard(e){d.value=void 0,c.value=`cards`,setTimeout(()=>d.value=e)}return u(()=>o.dataset,()=>{c.value=`sessions`,l.value=null,d.value=void 0}),(a,o)=>{let u=i(`v-tab`),h=i(`v-tabs`),g=i(`v-btn`);return n(),f(`div`,null,[t(h,{modelValue:c.value,"onUpdate:modelValue":o[0]||(o[0]=e=>c.value=e),density:`compact`,class:`mb-4`},{default:e(()=>[t(u,{value:`sessions`},{default:e(()=>[s(`Sessions (`+r(a.dataset.sessions.length)+`)`,1)]),_:1}),t(u,{value:`cards`},{default:e(()=>[s(`Cards (`+r(a.dataset.cardHistories.length)+`)`,1)]),_:1}),a.dataset.strategies?(n(),y(u,{key:0,value:`pipeline`},{default:e(()=>o[3]||(o[3]=[s(`Pipeline`)])),_:1})):b(``,!0)]),_:1},8,[`modelValue`]),c.value===`sessions`?(n(),f(p,{key:0},[l.value?(n(),f(p,{key:0},[t(g,{variant:`text`,size:`small`,"prepend-icon":`mdi-arrow-left`,class:`mb-2`,onClick:o[1]||(o[1]=e=>l.value=null)},{default:e(()=>o[4]||(o[4]=[s(` All sessions `)])),_:1}),t(ft,{dataset:a.dataset,"session-id":l.value,interpreters:a.interpreters,onOpenCard:openCard},null,8,[`dataset`,`session-id`,`interpreters`])],64)):(n(),y(Dt,{key:1,dataset:a.dataset,interpreters:a.interpreters,onOpen:o[2]||(o[2]=e=>l.value=e)},null,8,[`dataset`,`interpreters`]))],64)):c.value===`cards`?(n(),y(ne,{key:1,dataset:a.dataset,interpreters:a.interpreters,focus:d.value},null,8,[`dataset`,`interpreters`,`focus`])):c.value===`pipeline`&&a.dataset.strategies?(n(),y(vn,{key:2,strategies:a.dataset.strategies,"course-id":a.dataset.courseId,stats:m.value,"stats-label":a.dataset.username},null,8,[`strategies`,`course-id`,`stats`,`stats-label`])):b(``,!0)])}}});export{fetchLearnerDump as a,cardDossiers as i,U as n,fromDump as o,yn as r,M as t};
4
+ //# sourceMappingURL=admin-DCvFP6sY.js.map