@almadar/std 16.173.0 → 16.175.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/behaviors/lolo/infra/atoms/std-cross-reference.lolo +2 -4
  2. package/behaviors/lolo/ui/core/atoms/std-board.lolo +5 -9
  3. package/behaviors/lolo/ui/core/atoms/std-browse.lolo +8 -1
  4. package/behaviors/lolo/ui/core/atoms/std-esign-flow.lolo +2 -2
  5. package/behaviors/lolo/ui/core/atoms/std-event-log.lolo +3 -7
  6. package/behaviors/lolo/ui/core/atoms/std-form-advanced.lolo +1 -1
  7. package/behaviors/lolo/ui/core/atoms/std-image-upload-multi.lolo +1 -1
  8. package/behaviors/lolo/ui/core/atoms/std-list.lolo +3 -3
  9. package/behaviors/lolo/ui/core/atoms/std-modal.lolo +2 -2
  10. package/behaviors/lolo/ui/core/atoms/std-multi-party-flow.lolo +2 -4
  11. package/behaviors/lolo/ui/core/atoms/std-rating-review.lolo +5 -13
  12. package/behaviors/lolo/ui/core/atoms/std-recurrence.lolo +3 -7
  13. package/behaviors/lolo/ui/core/atoms/std-saved-search.lolo +1 -1
  14. package/behaviors/lolo/ui/core/atoms/std-signature-capture.lolo +2 -2
  15. package/behaviors/lolo/ui/core/atoms/std-step-flow.lolo +2 -4
  16. package/behaviors/lolo/ui/core/atoms/std-tag-taxonomy.lolo +1 -1
  17. package/behaviors/lolo/ui/core/atoms/std-thread.lolo +2 -2
  18. package/behaviors/lolo/ui/core/atoms/std-vote.lolo +2 -2
  19. package/behaviors/lolo/ui/core/atoms/std-wizard.lolo +3 -7
  20. package/behaviors/lolo/ui/core/atoms/ui-atlas-image.lolo +1 -1
  21. package/behaviors/lolo/ui/core/atoms/ui-atlas-panel.lolo +1 -1
  22. package/behaviors/lolo/ui/core/atoms/ui-center.lolo +1 -1
  23. package/behaviors/lolo/ui/core/atoms/ui-hstack.lolo +1 -1
  24. package/behaviors/lolo/ui/core/atoms/ui-icon.lolo +1 -1
  25. package/behaviors/lolo/ui/core/atoms/ui-stack.lolo +1 -1
  26. package/behaviors/lolo/ui/core/atoms/ui-typography.lolo +1 -1
  27. package/behaviors/lolo/ui/core/atoms/ui-vstack.lolo +1 -1
  28. package/behaviors/lolo/ui/core/molecules/ui-content-renderer.lolo +1 -1
  29. package/behaviors/lolo/ui/core/molecules/ui-form-layout.lolo +1 -1
  30. package/behaviors/lolo/ui/core/molecules/ui-grid.lolo +1 -1
  31. package/behaviors/lolo/ui/core/molecules/ui-table-view.lolo +4 -9
  32. package/behaviors/lolo/ui/core/organisms/ui-chat-bar.lolo +1 -1
  33. package/behaviors/lolo/ui/core/organisms/ui-dashboard-grid.lolo +1 -1
  34. package/behaviors/lolo/ui/core/organisms/ui-detail-panel.lolo +1 -1
  35. package/behaviors/lolo/ui/core/organisms/ui-entity-cards.lolo +1 -1
  36. package/behaviors/lolo/ui/core/organisms/ui-entity-list.lolo +1 -1
  37. package/behaviors/lolo/ui/core/organisms/ui-entity-table.lolo +1 -1
  38. package/behaviors/lolo/ui/core/organisms/ui-form-section.lolo +9 -3
  39. package/behaviors/lolo/ui/core/organisms/ui-form.lolo +9 -3
  40. package/behaviors/lolo/ui/core/organisms/ui-master-detail.lolo +1 -1
  41. package/behaviors/lolo/ui/core/organisms/ui-media-gallery.lolo +1 -1
  42. package/behaviors/lolo/ui/core/organisms/ui-segment-renderer.lolo +7 -1
  43. package/behaviors/lolo/ui/core/organisms/ui-stat-card.lolo +1 -1
  44. package/behaviors/lolo/ui/core/organisms/ui-subagent-trace-panel.lolo +1 -1
  45. package/behaviors/lolo/ui/game/atoms/ui-action-tile.lolo +1 -1
  46. package/behaviors/lolo/ui/game/atoms/ui-draw-shape-layer.lolo +41 -9
  47. package/behaviors/lolo/ui/game/atoms/ui-draw-shape.lolo +40 -8
  48. package/behaviors/lolo/ui/game/atoms/ui-draw-sprite-layer.lolo +13 -3
  49. package/behaviors/lolo/ui/game/atoms/ui-draw-sprite.lolo +12 -2
  50. package/behaviors/lolo/ui/game/atoms/ui-draw-text-layer.lolo +3 -3
  51. package/behaviors/lolo/ui/game/atoms/ui-draw-text.lolo +2 -2
  52. package/behaviors/lolo/ui/game/organisms/std-tactics-board-3d.lolo +32 -2
  53. package/behaviors/lolo/ui/learning/atoms/std-learn-classify.lolo +133 -23
  54. package/behaviors/lolo/ui/learning/atoms/std-learn-compare.lolo +397 -0
  55. package/behaviors/lolo/ui/learning/atoms/std-learn-coupled-sim.lolo +537 -0
  56. package/behaviors/lolo/ui/learning/atoms/std-learn-derivation.lolo +428 -0
  57. package/behaviors/lolo/ui/learning/atoms/std-learn-doser.lolo +520 -0
  58. package/behaviors/lolo/ui/learning/atoms/std-learn-estimate.lolo +419 -0
  59. package/behaviors/lolo/ui/learning/atoms/std-learn-goal-seek.lolo +591 -0
  60. package/behaviors/lolo/ui/learning/atoms/std-learn-grid-sim.lolo +425 -0
  61. package/behaviors/lolo/ui/learning/atoms/std-learn-hotspot.lolo +398 -0
  62. package/behaviors/lolo/ui/learning/atoms/std-learn-measure.lolo +325 -0
  63. package/behaviors/lolo/ui/learning/atoms/std-learn-perturb.lolo +494 -0
  64. package/behaviors/lolo/ui/learning/atoms/std-learn-predict.lolo +408 -0
  65. package/behaviors/lolo/ui/learning/atoms/std-learn-scatter-fit.lolo +805 -0
  66. package/behaviors/lolo/ui/learning/atoms/std-learn-scenario.lolo +307 -0
  67. package/behaviors/lolo/ui/learning/atoms/std-learn-sim-3d.lolo +318 -0
  68. package/behaviors/lolo/ui/learning/atoms/std-learn-speed-drill.lolo +336 -0
  69. package/behaviors/lolo/ui/learning/atoms/std-learn-tour-3d.lolo +409 -0
  70. package/behaviors/lolo/ui/learning/atoms/std-learn-transport.lolo +186 -0
  71. package/behaviors/lolo/ui/learning/atoms/std-learn-tree.lolo +522 -0
  72. package/behaviors/lolo/ui/learning/atoms/ui-algo-graph-canvas.lolo +192 -0
  73. package/behaviors/lolo/ui/learning/atoms/ui-algorithm-canvas.lolo +111 -2
  74. package/behaviors/lolo/ui/learning/atoms/ui-biology-canvas.lolo +193 -5
  75. package/behaviors/lolo/ui/learning/atoms/ui-chemistry-canvas.lolo +173 -5
  76. package/behaviors/lolo/ui/learning/atoms/ui-learning-canvas.lolo +48 -1
  77. package/behaviors/lolo/ui/learning/atoms/ui-math-canvas.lolo +141 -1
  78. package/behaviors/lolo/ui/learning/atoms/ui-physics-canvas.lolo +242 -5
  79. package/behaviors/lolo/ui/marketing/organisms/ui-book-viewer.lolo +1 -1
  80. package/behaviors/lolo/ui/marketing/organisms/ui-case-study-organism.lolo +1 -1
  81. package/behaviors/lolo/ui/marketing/organisms/ui-feature-grid-organism.lolo +1 -1
  82. package/behaviors/lolo/ui/marketing/organisms/ui-hero-organism.lolo +1 -1
  83. package/behaviors/lolo/ui/marketing/organisms/ui-pricing-organism.lolo +1 -1
  84. package/behaviors/lolo/ui/marketing/organisms/ui-showcase-organism.lolo +1 -1
  85. package/behaviors/lolo/ui/marketing/organisms/ui-stats-organism.lolo +1 -1
  86. package/behaviors/lolo/ui/marketing/organisms/ui-step-flow-organism.lolo +1 -1
  87. package/behaviors/lolo/ui/marketing/organisms/ui-team-organism.lolo +1 -1
  88. package/behaviors/registry/agent/atoms/std-agent-session.orb +22 -1
  89. package/behaviors/registry/agent/atoms/std-agent-tool-call.orb +38 -2
  90. package/behaviors/registry/agent/atoms/std-agent-tool-loop.orb +38 -2
  91. package/behaviors/registry/agent/organisms/std-agent-rabit.orb +23 -1
  92. package/behaviors/registry/infra/atoms/std-approval-gate.orb +8 -16
  93. package/behaviors/registry/infra/atoms/std-cache-aside.orb +31 -62
  94. package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +16 -32
  95. package/behaviors/registry/infra/atoms/std-cross-reference.orb +32 -4
  96. package/behaviors/registry/infra/atoms/std-data-erasure.orb +8 -16
  97. package/behaviors/registry/infra/atoms/std-mod-queue.orb +8 -16
  98. package/behaviors/registry/infra/atoms/std-rate-limiter.orb +14 -28
  99. package/behaviors/registry/infra/atoms/std-row-access-control.orb +30 -2
  100. package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +1 -2
  101. package/behaviors/registry/ui/core/atoms/std-board.orb +19 -5
  102. package/behaviors/registry/ui/core/atoms/std-browse.orb +29 -7
  103. package/behaviors/registry/ui/core/atoms/std-dashboard-grid-embedded.orb +1 -2
  104. package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +3 -5
  105. package/behaviors/registry/ui/core/atoms/std-esign-request.orb +3 -6
  106. package/behaviors/registry/ui/core/atoms/std-event-log.orb +17 -3
  107. package/behaviors/registry/ui/core/atoms/std-export.orb +2 -4
  108. package/behaviors/registry/ui/core/atoms/std-form-advanced.orb +1 -1
  109. package/behaviors/registry/ui/core/atoms/std-gallery.orb +9 -18
  110. package/behaviors/registry/ui/core/atoms/std-graphs.orb +15 -1
  111. package/behaviors/registry/ui/core/atoms/std-import.orb +2 -4
  112. package/behaviors/registry/ui/core/atoms/std-list.orb +4 -6
  113. package/behaviors/registry/ui/core/atoms/std-modal.orb +2 -2
  114. package/behaviors/registry/ui/core/atoms/std-multi-party-flow.orb +16 -2
  115. package/behaviors/registry/ui/core/atoms/std-pagination.orb +15 -1
  116. package/behaviors/registry/ui/core/atoms/std-rating-review.orb +19 -5
  117. package/behaviors/registry/ui/core/atoms/std-recurrence.orb +17 -3
  118. package/behaviors/registry/ui/core/atoms/std-rich-editor.orb +15 -1
  119. package/behaviors/registry/ui/core/atoms/std-scatter.orb +15 -1
  120. package/behaviors/registry/ui/core/atoms/std-signature-capture.orb +2 -2
  121. package/behaviors/registry/ui/core/atoms/std-stats.orb +15 -1
  122. package/behaviors/registry/ui/core/atoms/std-step-flow.orb +16 -2
  123. package/behaviors/registry/ui/core/atoms/std-thread.orb +2 -2
  124. package/behaviors/registry/ui/core/atoms/std-vote.orb +2 -2
  125. package/behaviors/registry/ui/core/atoms/std-wizard.orb +17 -3
  126. package/behaviors/registry/ui/core/atoms/ui-atlas-image.orb +4 -1
  127. package/behaviors/registry/ui/core/atoms/ui-atlas-panel.orb +4 -1
  128. package/behaviors/registry/ui/core/atoms/ui-center.orb +4 -1
  129. package/behaviors/registry/ui/core/atoms/ui-hstack.orb +4 -1
  130. package/behaviors/registry/ui/core/atoms/ui-icon.orb +4 -1
  131. package/behaviors/registry/ui/core/atoms/ui-stack.orb +4 -1
  132. package/behaviors/registry/ui/core/atoms/ui-typography.orb +4 -1
  133. package/behaviors/registry/ui/core/atoms/ui-vstack.orb +4 -1
  134. package/behaviors/registry/ui/core/molecules/ui-accordion.orb +3 -3
  135. package/behaviors/registry/ui/core/molecules/ui-content-renderer.orb +4 -1
  136. package/behaviors/registry/ui/core/molecules/ui-form-layout.orb +4 -1
  137. package/behaviors/registry/ui/core/molecules/ui-grid.orb +4 -1
  138. package/behaviors/registry/ui/core/molecules/ui-table-view.orb +4 -39
  139. package/behaviors/registry/ui/core/molecules/ui-tabs.orb +2 -2
  140. package/behaviors/registry/ui/core/molecules/ui-wizard-container.orb +1 -1
  141. package/behaviors/registry/ui/core/organisms/ui-chat-bar.orb +4 -1
  142. package/behaviors/registry/ui/core/organisms/ui-dashboard-grid.orb +5 -2
  143. package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +5 -2
  144. package/behaviors/registry/ui/core/organisms/ui-entity-cards.orb +4 -1
  145. package/behaviors/registry/ui/core/organisms/ui-entity-list.orb +4 -1
  146. package/behaviors/registry/ui/core/organisms/ui-entity-table.orb +4 -1
  147. package/behaviors/registry/ui/core/organisms/ui-form-section.orb +34 -2
  148. package/behaviors/registry/ui/core/organisms/ui-form.orb +34 -2
  149. package/behaviors/registry/ui/core/organisms/ui-master-detail.orb +4 -1
  150. package/behaviors/registry/ui/core/organisms/ui-media-gallery.orb +4 -1
  151. package/behaviors/registry/ui/core/organisms/ui-segment-renderer.orb +24 -2
  152. package/behaviors/registry/ui/core/organisms/ui-stat-card.orb +4 -1
  153. package/behaviors/registry/ui/core/organisms/ui-subagent-trace-panel.orb +4 -1
  154. package/behaviors/registry/ui/core/organisms/ui-tabbed-container.orb +1 -1
  155. package/behaviors/registry/ui/core/organisms/ui-ui-slot-renderer.orb +1 -1
  156. package/behaviors/registry/ui/game/atoms/std-fx-particles.orb +35 -1
  157. package/behaviors/registry/ui/game/atoms/ui-action-tile.orb +4 -1
  158. package/behaviors/registry/ui/game/atoms/ui-draw-shape-layer.orb +183 -13
  159. package/behaviors/registry/ui/game/atoms/ui-draw-shape.orb +104 -9
  160. package/behaviors/registry/ui/game/atoms/ui-draw-sprite-layer.orb +56 -2
  161. package/behaviors/registry/ui/game/atoms/ui-draw-sprite.orb +36 -4
  162. package/behaviors/registry/ui/game/atoms/ui-draw-text-layer.orb +21 -2
  163. package/behaviors/registry/ui/game/atoms/ui-draw-text.orb +19 -4
  164. package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +173 -2
  165. package/behaviors/registry/ui/learning/atoms/std-learn-classify.orb +1288 -197
  166. package/behaviors/registry/ui/learning/atoms/std-learn-compare.orb +2814 -0
  167. package/behaviors/registry/ui/learning/atoms/std-learn-coupled-sim.orb +3183 -0
  168. package/behaviors/registry/ui/learning/atoms/std-learn-derivation.orb +2512 -0
  169. package/behaviors/registry/ui/learning/atoms/std-learn-doser.orb +3678 -0
  170. package/behaviors/registry/ui/learning/atoms/std-learn-estimate.orb +2394 -0
  171. package/behaviors/registry/ui/learning/atoms/std-learn-goal-seek.orb +3951 -0
  172. package/behaviors/registry/ui/learning/atoms/std-learn-grid-sim.orb +3458 -0
  173. package/behaviors/registry/ui/learning/atoms/std-learn-hotspot.orb +2646 -0
  174. package/behaviors/registry/ui/learning/atoms/std-learn-measure.orb +1979 -0
  175. package/behaviors/registry/ui/learning/atoms/std-learn-perturb.orb +2994 -0
  176. package/behaviors/registry/ui/learning/atoms/std-learn-predict.orb +2682 -0
  177. package/behaviors/registry/ui/learning/atoms/std-learn-scatter-fit.orb +6539 -0
  178. package/behaviors/registry/ui/learning/atoms/std-learn-scenario.orb +1842 -0
  179. package/behaviors/registry/ui/learning/atoms/std-learn-sim-3d.orb +1648 -0
  180. package/behaviors/registry/ui/learning/atoms/std-learn-speed-drill.orb +2307 -0
  181. package/behaviors/registry/ui/learning/atoms/std-learn-tour-3d.orb +3118 -0
  182. package/behaviors/registry/ui/learning/atoms/std-learn-transport.orb +986 -0
  183. package/behaviors/registry/ui/learning/atoms/std-learn-tree.orb +3333 -0
  184. package/behaviors/registry/ui/learning/atoms/ui-algo-graph-canvas.orb +716 -0
  185. package/behaviors/registry/ui/learning/atoms/ui-algorithm-canvas.orb +679 -5
  186. package/behaviors/registry/ui/learning/atoms/ui-biology-canvas.orb +962 -18
  187. package/behaviors/registry/ui/learning/atoms/ui-chemistry-canvas.orb +919 -30
  188. package/behaviors/registry/ui/learning/atoms/ui-learning-canvas.orb +372 -1
  189. package/behaviors/registry/ui/learning/atoms/ui-math-canvas.orb +936 -16
  190. package/behaviors/registry/ui/learning/atoms/ui-physics-canvas.orb +1328 -43
  191. package/behaviors/registry/ui/marketing/atoms/std-marketing-article.orb +1 -2
  192. package/behaviors/registry/ui/marketing/atoms/std-marketing-footer.orb +1 -2
  193. package/behaviors/registry/ui/marketing/atoms/std-marketing-split.orb +1 -2
  194. package/behaviors/registry/ui/marketing/atoms/std-marketing-stats.orb +1 -2
  195. package/behaviors/registry/ui/marketing/atoms/std-marketing-steps.orb +1 -2
  196. package/behaviors/registry/ui/marketing/atoms/std-marketing-team.orb +1 -2
  197. package/behaviors/registry/ui/marketing/organisms/ui-book-viewer.orb +4 -1
  198. package/behaviors/registry/ui/marketing/organisms/ui-case-study-organism.orb +4 -1
  199. package/behaviors/registry/ui/marketing/organisms/ui-feature-grid-organism.orb +4 -1
  200. package/behaviors/registry/ui/marketing/organisms/ui-hero-organism.orb +4 -1
  201. package/behaviors/registry/ui/marketing/organisms/ui-pricing-organism.orb +4 -1
  202. package/behaviors/registry/ui/marketing/organisms/ui-showcase-organism.orb +4 -1
  203. package/behaviors/registry/ui/marketing/organisms/ui-stats-organism.orb +4 -1
  204. package/behaviors/registry/ui/marketing/organisms/ui-step-flow-organism.orb +4 -1
  205. package/behaviors/registry/ui/marketing/organisms/ui-team-organism.orb +4 -1
  206. package/dist/behaviors/exports-reader.js +3704 -2189
  207. package/dist/behaviors/functions/index.d.ts +2638 -254
  208. package/dist/behaviors/functions/index.js +3648 -2190
  209. package/dist/behaviors/index.d.ts +1 -1
  210. package/dist/behaviors/index.js +3705 -2190
  211. package/dist/behaviors/query.js +3704 -2189
  212. package/dist/behaviors-embeddings.hash.json +3 -3
  213. package/dist/behaviors-embeddings.json +289 -213
  214. package/dist/behaviors-registry.json +7900 -587
  215. package/dist/index.d.ts +1 -1
  216. package/dist/index.js +3705 -2190
  217. package/dist/knob-embeddings.hash.json +3 -3
  218. package/dist/knob-embeddings.json +1 -1
  219. package/dist/registry/factory-signatures.json +1 -1
  220. package/package.json +2 -2
@@ -0,0 +1,336 @@
1
+ app std-learn-speed-drill "1.0.0"
2
+ "Generic speeded-response drill — a config-declared item roster of prompt + options runs against a live countdown: answering while the clock runs scores the base points plus a speed bonus proportional to the time left, letting the clock hit zero counts as a miss and reveals the answer, and a streak counter rewards consecutive hits with an end-of-round summary of score and best streak. All vocabulary and timing is config-declared, so the same mechanism serves any fluency drill: times tables, sight vocabulary, chemical symbols, flag recognition, interval identification — anywhere fast retrieval is the skill. Standalone by default; behind a lab router set matchMode and it renders only when MODE_SELECTED matches."
3
+ orbital SpeedDrillOrbital {
4
+ type SpeedDrillItem = {
5
+ prompt : string!
6
+ options : [string]!
7
+ correctIndex : number!
8
+ }
9
+
10
+ entity SpeedDrillScene [runtime] {
11
+ id : string!
12
+ active : boolean = false
13
+ title : string
14
+ itemIndex : number = 0
15
+ totalItems : number = 0
16
+ remaining : number = 0
17
+ running : boolean = false
18
+ verdict : string
19
+ score : number = 0
20
+ streak : number = 0
21
+ bestStreak : number = 0
22
+ done : boolean = false
23
+ promptText : string
24
+ options : [string]
25
+ correctIndex : number = 0
26
+ feedback : string
27
+ view : [node]
28
+ }
29
+
30
+ trait SpeedDrillSim -> @rebindable SpeedDrillScene [interaction, instance] {
31
+ initial: idle
32
+
33
+ state idle {
34
+ INIT -> idle when (== @config.matchMode "")
35
+ (let (
36
+ (first (array/nth @config.items 0))
37
+ )
38
+ (do
39
+ (set @entity.active true)
40
+ (set @entity.title @config.title)
41
+ (set @entity.itemIndex 0)
42
+ (set @entity.totalItems (array/len @config.items))
43
+ (set @entity.remaining (* @config.timeLimit 10))
44
+ (set @entity.running true)
45
+ (set @entity.verdict "")
46
+ (set @entity.score 0)
47
+ (set @entity.streak 0)
48
+ (set @entity.bestStreak 0)
49
+ (set @entity.done false)
50
+ (set @entity.promptText (object/get @first prompt))
51
+ (set @entity.options (object/get @first options))
52
+ (set @entity.correctIndex (object/get @first correctIndex))
53
+ (set @entity.feedback "")
54
+ (set @entity.view [
55
+ { type: card, variant: bordered, padding: md, children: [
56
+ { type: typography, variant: h4, content: @entity.promptText }
57
+ ] }
58
+ ])))
59
+ (render-ui main {
60
+ type: box
61
+ padding: md
62
+ children: [
63
+ { type: stack, direction: vertical, gap: md, children: [
64
+ { type: typography, variant: h4, content: @entity.title },
65
+ { type: progress-bar, value: (+ @entity.itemIndex 1), max: @entity.totalItems, showPercentage: false, label: (str/concat "Item " (str/concat "" (+ @entity.itemIndex 1)) " of " (str/concat "" @entity.totalItems)) },
66
+ { type: progress-bar, value: @entity.remaining, max: (* @config.timeLimit 10), showPercentage: false, label: (str/concat "Time left: " (math/round (/ @entity.remaining 10) 1) "s") },
67
+ { type: stack, direction: vertical, gap: md, children: @entity.view },
68
+ { type: stack, direction: horizontal, gap: xs, children: (array/map (array/range 0 (array/len @entity.options)) (fn (i)
69
+ { type: button, action: ANSWER, actionPayload: { index: @i }, label: (array/nth @entity.options @i), variant: secondary, size: sm, disabled: (if @entity.running false true) })) },
70
+ { type: typography, variant: caption, content: @entity.feedback },
71
+ { type: stack, direction: horizontal, gap: sm, children: [
72
+ { type: button, action: NEXT, label: @config.nextLabel, variant: primary, disabled: (if (and (== @entity.running false) (and (!= @entity.verdict "") (== @entity.done false))) false true) },
73
+ { type: button, action: RETRY, label: @config.retryLabel, variant: ghost, disabled: (if @entity.done false true) }
74
+ ] },
75
+ { type: stat-display, label: "Score", value: @entity.score, max: 0 },
76
+ { type: typography, variant: caption, content: (str/concat "Streak: " (str/concat "" @entity.streak) " · best: " (str/concat "" @entity.bestStreak)) }
77
+ ] }
78
+ ]
79
+ })
80
+
81
+ MODE_SELECTED -> idle when (== ?mode @config.matchMode)
82
+ (let (
83
+ (first (array/nth @config.items 0))
84
+ )
85
+ (do
86
+ (set @entity.active true)
87
+ (set @entity.title @config.title)
88
+ (set @entity.itemIndex 0)
89
+ (set @entity.totalItems (array/len @config.items))
90
+ (set @entity.remaining (* @config.timeLimit 10))
91
+ (set @entity.running true)
92
+ (set @entity.verdict "")
93
+ (set @entity.score 0)
94
+ (set @entity.streak 0)
95
+ (set @entity.bestStreak 0)
96
+ (set @entity.done false)
97
+ (set @entity.promptText (object/get @first prompt))
98
+ (set @entity.options (object/get @first options))
99
+ (set @entity.correctIndex (object/get @first correctIndex))
100
+ (set @entity.feedback "")
101
+ (set @entity.view [
102
+ { type: card, variant: bordered, padding: md, children: [
103
+ { type: typography, variant: h4, content: @entity.promptText }
104
+ ] }
105
+ ])))
106
+ (render-ui main {
107
+ type: box
108
+ padding: md
109
+ children: [
110
+ { type: stack, direction: vertical, gap: md, children: [
111
+ { type: typography, variant: h4, content: @entity.title },
112
+ { type: progress-bar, value: (+ @entity.itemIndex 1), max: @entity.totalItems, showPercentage: false, label: (str/concat "Item " (str/concat "" (+ @entity.itemIndex 1)) " of " (str/concat "" @entity.totalItems)) },
113
+ { type: progress-bar, value: @entity.remaining, max: (* @config.timeLimit 10), showPercentage: false, label: (str/concat "Time left: " (math/round (/ @entity.remaining 10) 1) "s") },
114
+ { type: stack, direction: vertical, gap: md, children: @entity.view },
115
+ { type: stack, direction: horizontal, gap: xs, children: (array/map (array/range 0 (array/len @entity.options)) (fn (i)
116
+ { type: button, action: ANSWER, actionPayload: { index: @i }, label: (array/nth @entity.options @i), variant: secondary, size: sm, disabled: (if @entity.running false true) })) },
117
+ { type: typography, variant: caption, content: @entity.feedback },
118
+ { type: stack, direction: horizontal, gap: sm, children: [
119
+ { type: button, action: NEXT, label: @config.nextLabel, variant: primary, disabled: (if (and (== @entity.running false) (and (!= @entity.verdict "") (== @entity.done false))) false true) },
120
+ { type: button, action: RETRY, label: @config.retryLabel, variant: ghost, disabled: (if @entity.done false true) }
121
+ ] },
122
+ { type: stat-display, label: "Score", value: @entity.score, max: 0 },
123
+ { type: typography, variant: caption, content: (str/concat "Streak: " (str/concat "" @entity.streak) " · best: " (str/concat "" @entity.bestStreak)) }
124
+ ] }
125
+ ]
126
+ })
127
+
128
+ ANSWER -> idle when (and (== @entity.active true) (and (== @entity.running true) (== @entity.done false)))
129
+ (let (
130
+ (correct (== ?index @entity.correctIndex))
131
+ (bonus (math/round (/ @entity.remaining 10) 1))
132
+ (points (if @correct (+ @config.basePoints (math/round (* @config.speedBonus (/ @entity.remaining (* @config.timeLimit 10))) 0)) 0))
133
+ (newStreak (if @correct (+ @entity.streak 1) 0))
134
+ )
135
+ (do
136
+ (set @entity.running false)
137
+ (set @entity.verdict (if @correct "correct" "wrong"))
138
+ (set @entity.score (+ @entity.score @points))
139
+ (set @entity.streak @newStreak)
140
+ (set @entity.bestStreak (math/max @entity.bestStreak @newStreak))
141
+ (set @entity.feedback (if @correct
142
+ (str/concat "Correct with " @bonus "s to spare — +" (str/concat "" @points) " points.")
143
+ (str/concat "Not quite — the answer was: " (array/nth @entity.options @entity.correctIndex))))))
144
+ (emit ANSWER_JUDGED { correct: (== @entity.verdict "correct"), timeLeftTenths: @entity.remaining, score: @entity.score, streak: @entity.streak })
145
+
146
+ NEXT -> idle when (and (== @entity.active true) (and (== @entity.running false) (and (!= @entity.verdict "") (== @entity.done false))))
147
+ (let (
148
+ (nextIndex (+ @entity.itemIndex 1))
149
+ (finished (>= @nextIndex (array/len @config.items)))
150
+ (next (array/nth @config.items (math/min @nextIndex (- (array/len @config.items) 1))))
151
+ )
152
+ (do
153
+ (set @entity.itemIndex (if @finished @entity.itemIndex @nextIndex))
154
+ (set @entity.done (if @finished true false))
155
+ (set @entity.remaining (if @finished 0 (* @config.timeLimit 10)))
156
+ (set @entity.running (if @finished false true))
157
+ (set @entity.verdict "")
158
+ (set @entity.promptText (if @finished @entity.promptText (object/get @next prompt)))
159
+ (set @entity.options (if @finished [] (object/get @next options)))
160
+ (set @entity.correctIndex (if @finished @entity.correctIndex (object/get @next correctIndex)))
161
+ (set @entity.feedback (if @finished (str/concat "Round complete — final score " (str/concat "" @entity.score) ", best streak " (str/concat "" @entity.bestStreak) ".") ""))
162
+ (set @entity.view (if @finished
163
+ [
164
+ { type: typography, variant: h4, content: "Round Complete" },
165
+ { type: stat-display, label: "Final score", value: @entity.score, max: 0 }
166
+ ]
167
+ [
168
+ { type: card, variant: bordered, padding: md, children: [
169
+ { type: typography, variant: h4, content: @entity.promptText }
170
+ ] }
171
+ ])))
172
+ )
173
+ (render-ui main {
174
+ type: box
175
+ padding: md
176
+ children: [
177
+ { type: stack, direction: vertical, gap: md, children: [
178
+ { type: typography, variant: h4, content: @entity.title },
179
+ { type: progress-bar, value: (+ @entity.itemIndex 1), max: @entity.totalItems, showPercentage: false, label: (str/concat "Item " (str/concat "" (+ @entity.itemIndex 1)) " of " (str/concat "" @entity.totalItems)) },
180
+ { type: progress-bar, value: @entity.remaining, max: (* @config.timeLimit 10), showPercentage: false, label: (str/concat "Time left: " (math/round (/ @entity.remaining 10) 1) "s") },
181
+ { type: stack, direction: vertical, gap: md, children: @entity.view },
182
+ { type: stack, direction: horizontal, gap: xs, children: (array/map (array/range 0 (array/len @entity.options)) (fn (i)
183
+ { type: button, action: ANSWER, actionPayload: { index: @i }, label: (array/nth @entity.options @i), variant: secondary, size: sm, disabled: (if @entity.running false true) })) },
184
+ { type: typography, variant: caption, content: @entity.feedback },
185
+ { type: stack, direction: horizontal, gap: sm, children: [
186
+ { type: button, action: NEXT, label: @config.nextLabel, variant: primary, disabled: (if (and (== @entity.running false) (and (!= @entity.verdict "") (== @entity.done false))) false true) },
187
+ { type: button, action: RETRY, label: @config.retryLabel, variant: ghost, disabled: (if @entity.done false true) }
188
+ ] },
189
+ { type: stat-display, label: "Score", value: @entity.score, max: 0 },
190
+ { type: typography, variant: caption, content: (str/concat "Streak: " (str/concat "" @entity.streak) " · best: " (str/concat "" @entity.bestStreak)) }
191
+ ] }
192
+ ]
193
+ })
194
+ (emit PROMPT_ADVANCED { itemIndex: @entity.itemIndex, done: @entity.done, score: @entity.score })
195
+
196
+ RETRY -> idle when (and (== @entity.active true) (== @entity.done true))
197
+ (let (
198
+ (first (array/nth @config.items 0))
199
+ )
200
+ (do
201
+ (set @entity.itemIndex 0)
202
+ (set @entity.remaining (* @config.timeLimit 10))
203
+ (set @entity.running true)
204
+ (set @entity.verdict "")
205
+ (set @entity.score 0)
206
+ (set @entity.streak 0)
207
+ (set @entity.bestStreak 0)
208
+ (set @entity.done false)
209
+ (set @entity.promptText (object/get @first prompt))
210
+ (set @entity.options (object/get @first options))
211
+ (set @entity.correctIndex (object/get @first correctIndex))
212
+ (set @entity.feedback "")
213
+ (set @entity.view [
214
+ { type: card, variant: bordered, padding: md, children: [
215
+ { type: typography, variant: h4, content: @entity.promptText }
216
+ ] }
217
+ ])))
218
+ (render-ui main {
219
+ type: box
220
+ padding: md
221
+ children: [
222
+ { type: stack, direction: vertical, gap: md, children: [
223
+ { type: typography, variant: h4, content: @entity.title },
224
+ { type: progress-bar, value: (+ @entity.itemIndex 1), max: @entity.totalItems, showPercentage: false, label: (str/concat "Item " (str/concat "" (+ @entity.itemIndex 1)) " of " (str/concat "" @entity.totalItems)) },
225
+ { type: progress-bar, value: @entity.remaining, max: (* @config.timeLimit 10), showPercentage: false, label: (str/concat "Time left: " (math/round (/ @entity.remaining 10) 1) "s") },
226
+ { type: stack, direction: vertical, gap: md, children: @entity.view },
227
+ { type: stack, direction: horizontal, gap: xs, children: (array/map (array/range 0 (array/len @entity.options)) (fn (i)
228
+ { type: button, action: ANSWER, actionPayload: { index: @i }, label: (array/nth @entity.options @i), variant: secondary, size: sm, disabled: (if @entity.running false true) })) },
229
+ { type: typography, variant: caption, content: @entity.feedback },
230
+ { type: stack, direction: horizontal, gap: sm, children: [
231
+ { type: button, action: NEXT, label: @config.nextLabel, variant: primary, disabled: (if (and (== @entity.running false) (and (!= @entity.verdict "") (== @entity.done false))) false true) },
232
+ { type: button, action: RETRY, label: @config.retryLabel, variant: ghost, disabled: (if @entity.done false true) }
233
+ ] },
234
+ { type: stat-display, label: "Score", value: @entity.score, max: 0 },
235
+ { type: typography, variant: caption, content: (str/concat "Streak: " (str/concat "" @entity.streak) " · best: " (str/concat "" @entity.bestStreak)) }
236
+ ] }
237
+ ]
238
+ })
239
+ (emit ROUND_RESTARTED { totalItems: @entity.totalItems })
240
+ }
241
+
242
+ ticks {
243
+ speedTick every 100ms
244
+ when (and (== @entity.active true) (== @entity.running true))
245
+ (set @entity.remaining (math/max 0 (- @entity.remaining 1)))
246
+ (set @entity.verdict (if (== @entity.remaining 0) "timeout" @entity.verdict))
247
+ (set @entity.feedback (if (== @entity.remaining 0) (str/concat "Time's up — the answer was: " (array/nth @entity.options @entity.correctIndex)) @entity.feedback))
248
+ (set @entity.streak (if (== @entity.remaining 0) 0 @entity.streak))
249
+ (set @entity.running (if (== @entity.remaining 0) false true))
250
+ }
251
+
252
+ listens {
253
+ MODE_SELECTED {
254
+ mode : string
255
+ }
256
+ @description "Lab router broadcast naming the active mode; this instrument renders when the mode equals matchMode, otherwise renders null."
257
+ @tier "domain"
258
+ ANSWER {
259
+ index : number
260
+ }
261
+ @description "Learner picked an option while the clock was running — index is the chosen option; it is judged immediately and scored with a speed bonus."
262
+ @tier "domain"
263
+ NEXT {
264
+ }
265
+ @description "Learner advanced to the next item after a verdict (answered or timed out); past the last item this completes the round."
266
+ @tier "domain"
267
+ RETRY {
268
+ }
269
+ @description "Learner restarted the round from the first item with a cleared score and streak."
270
+ @tier "domain"
271
+ }
272
+
273
+ emits {
274
+ ANSWER_JUDGED -> external {
275
+ correct : boolean
276
+ timeLeftTenths : number
277
+ score : number
278
+ streak : number
279
+ }
280
+ @description "The verdict of a speeded answer: correctness, tenths of a second left on the clock, and the running score and streak — a composed listener (coach, grader) can subscribe; a harmless no-op when the atom runs standalone."
281
+ @synonyms "speed drill, reaction time, fluency, timed quiz, countdown, rapid recall"
282
+ @tier "domain"
283
+ PROMPT_ADVANCED -> external {
284
+ itemIndex : number
285
+ done : boolean
286
+ score : number
287
+ }
288
+ @description "The learner moved to the next item (or completed the round) with the running score."
289
+ @tier "domain"
290
+ ROUND_RESTARTED -> external {
291
+ totalItems : number
292
+ }
293
+ @description "The learner restarted the round from scratch."
294
+ @tier "domain"
295
+ }
296
+
297
+ config {
298
+ matchMode : string = ""
299
+ @label "Match Mode"
300
+ @description "When composed behind a lab router, the MODE_SELECTED mode value this instrument responds to. Empty string means standalone — render immediately on INIT."
301
+ @tier "presentation"
302
+ title : string = "Speed Drill"
303
+ @label "Title"
304
+ @description "Title shown above the drill."
305
+ @tier "presentation"
306
+ items : [SpeedDrillItem] = [
307
+ { prompt: "7 × 8", options: ["54", "56", "63", "48"], correctIndex: 1 },
308
+ { prompt: "9 × 6", options: ["54", "56", "45", "63"], correctIndex: 0 },
309
+ { prompt: "12 × 12", options: ["124", "132", "144", "148"], correctIndex: 2 }
310
+ ]
311
+ @label "Items"
312
+ @description "The drill roster; each item carries a prompt, its options, and the index of the correct option. Realizations declare their own subject's items here."
313
+ @tier "domain"
314
+ timeLimit : number = 6
315
+ @label "Time Limit"
316
+ @description "Seconds the learner has to answer each item before it counts as a miss."
317
+ @tier "domain"
318
+ basePoints : number = 10
319
+ @label "Base Points"
320
+ @description "Points for a correct answer regardless of speed."
321
+ @tier "domain"
322
+ speedBonus : number = 10
323
+ @label "Speed Bonus"
324
+ @description "Maximum extra points awarded in proportion to the time left on the clock."
325
+ @tier "domain"
326
+ nextLabel : string = "Next"
327
+ @label "Next Label"
328
+ @tier "presentation"
329
+ retryLabel : string = "Try Again"
330
+ @label "Retry Label"
331
+ @tier "presentation"
332
+ }
333
+ }
334
+
335
+ page "/learn-speed-drill" as SpeedDrillPage -> SpeedDrillSim
336
+ }