@almadar/std 16.173.0 → 16.174.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.
- package/behaviors/lolo/infra/atoms/std-cross-reference.lolo +2 -4
- package/behaviors/lolo/ui/core/atoms/std-board.lolo +5 -9
- package/behaviors/lolo/ui/core/atoms/std-browse.lolo +8 -1
- package/behaviors/lolo/ui/core/atoms/std-esign-flow.lolo +2 -2
- package/behaviors/lolo/ui/core/atoms/std-event-log.lolo +3 -7
- package/behaviors/lolo/ui/core/atoms/std-form-advanced.lolo +1 -1
- package/behaviors/lolo/ui/core/atoms/std-image-upload-multi.lolo +1 -1
- package/behaviors/lolo/ui/core/atoms/std-list.lolo +3 -3
- package/behaviors/lolo/ui/core/atoms/std-modal.lolo +2 -2
- package/behaviors/lolo/ui/core/atoms/std-multi-party-flow.lolo +2 -4
- package/behaviors/lolo/ui/core/atoms/std-rating-review.lolo +5 -13
- package/behaviors/lolo/ui/core/atoms/std-recurrence.lolo +3 -7
- package/behaviors/lolo/ui/core/atoms/std-saved-search.lolo +1 -1
- package/behaviors/lolo/ui/core/atoms/std-signature-capture.lolo +2 -2
- package/behaviors/lolo/ui/core/atoms/std-step-flow.lolo +2 -4
- package/behaviors/lolo/ui/core/atoms/std-tag-taxonomy.lolo +1 -1
- package/behaviors/lolo/ui/core/atoms/std-thread.lolo +2 -2
- package/behaviors/lolo/ui/core/atoms/std-vote.lolo +2 -2
- package/behaviors/lolo/ui/core/atoms/std-wizard.lolo +3 -7
- package/behaviors/lolo/ui/core/atoms/ui-atlas-image.lolo +1 -1
- package/behaviors/lolo/ui/core/atoms/ui-atlas-panel.lolo +1 -1
- package/behaviors/lolo/ui/core/atoms/ui-center.lolo +1 -1
- package/behaviors/lolo/ui/core/atoms/ui-hstack.lolo +1 -1
- package/behaviors/lolo/ui/core/atoms/ui-icon.lolo +1 -1
- package/behaviors/lolo/ui/core/atoms/ui-stack.lolo +1 -1
- package/behaviors/lolo/ui/core/atoms/ui-typography.lolo +1 -1
- package/behaviors/lolo/ui/core/atoms/ui-vstack.lolo +1 -1
- package/behaviors/lolo/ui/core/molecules/ui-content-renderer.lolo +1 -1
- package/behaviors/lolo/ui/core/molecules/ui-form-layout.lolo +1 -1
- package/behaviors/lolo/ui/core/molecules/ui-grid.lolo +1 -1
- package/behaviors/lolo/ui/core/organisms/ui-chat-bar.lolo +1 -1
- package/behaviors/lolo/ui/core/organisms/ui-dashboard-grid.lolo +1 -1
- package/behaviors/lolo/ui/core/organisms/ui-detail-panel.lolo +1 -1
- package/behaviors/lolo/ui/core/organisms/ui-entity-cards.lolo +1 -1
- package/behaviors/lolo/ui/core/organisms/ui-entity-list.lolo +1 -1
- package/behaviors/lolo/ui/core/organisms/ui-entity-table.lolo +1 -1
- package/behaviors/lolo/ui/core/organisms/ui-form-section.lolo +9 -3
- package/behaviors/lolo/ui/core/organisms/ui-form.lolo +9 -3
- package/behaviors/lolo/ui/core/organisms/ui-master-detail.lolo +1 -1
- package/behaviors/lolo/ui/core/organisms/ui-media-gallery.lolo +1 -1
- package/behaviors/lolo/ui/core/organisms/ui-segment-renderer.lolo +7 -1
- package/behaviors/lolo/ui/core/organisms/ui-stat-card.lolo +1 -1
- package/behaviors/lolo/ui/core/organisms/ui-subagent-trace-panel.lolo +1 -1
- package/behaviors/lolo/ui/game/atoms/ui-action-tile.lolo +1 -1
- package/behaviors/lolo/ui/game/atoms/ui-draw-shape-layer.lolo +41 -9
- package/behaviors/lolo/ui/game/atoms/ui-draw-shape.lolo +40 -8
- package/behaviors/lolo/ui/game/atoms/ui-draw-sprite-layer.lolo +13 -3
- package/behaviors/lolo/ui/game/atoms/ui-draw-sprite.lolo +12 -2
- package/behaviors/lolo/ui/game/atoms/ui-draw-text-layer.lolo +3 -3
- package/behaviors/lolo/ui/game/atoms/ui-draw-text.lolo +2 -2
- package/behaviors/lolo/ui/game/organisms/std-tactics-board-3d.lolo +32 -2
- package/behaviors/lolo/ui/learning/atoms/std-learn-classify.lolo +1 -1
- package/behaviors/lolo/ui/learning/atoms/std-learn-compare.lolo +397 -0
- package/behaviors/lolo/ui/learning/atoms/std-learn-coupled-sim.lolo +537 -0
- package/behaviors/lolo/ui/learning/atoms/std-learn-estimate.lolo +419 -0
- package/behaviors/lolo/ui/learning/atoms/std-learn-goal-seek.lolo +591 -0
- package/behaviors/lolo/ui/learning/atoms/std-learn-grid-sim.lolo +425 -0
- package/behaviors/lolo/ui/learning/atoms/std-learn-hotspot.lolo +398 -0
- package/behaviors/lolo/ui/learning/atoms/std-learn-measure.lolo +325 -0
- package/behaviors/lolo/ui/learning/atoms/std-learn-perturb.lolo +494 -0
- package/behaviors/lolo/ui/learning/atoms/std-learn-predict.lolo +408 -0
- package/behaviors/lolo/ui/learning/atoms/std-learn-scenario.lolo +307 -0
- package/behaviors/lolo/ui/learning/atoms/std-learn-sim-3d.lolo +318 -0
- package/behaviors/lolo/ui/learning/atoms/std-learn-speed-drill.lolo +336 -0
- package/behaviors/lolo/ui/learning/atoms/std-learn-tour-3d.lolo +380 -0
- package/behaviors/lolo/ui/learning/atoms/ui-biology-canvas.lolo +43 -4
- package/behaviors/lolo/ui/learning/atoms/ui-chemistry-canvas.lolo +41 -4
- package/behaviors/lolo/ui/learning/atoms/ui-physics-canvas.lolo +43 -4
- package/behaviors/lolo/ui/marketing/organisms/ui-book-viewer.lolo +1 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-case-study-organism.lolo +1 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-feature-grid-organism.lolo +1 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-hero-organism.lolo +1 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-pricing-organism.lolo +1 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-showcase-organism.lolo +1 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-stats-organism.lolo +1 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-step-flow-organism.lolo +1 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-team-organism.lolo +1 -1
- package/behaviors/registry/agent/atoms/std-agent-session.orb +22 -1
- package/behaviors/registry/agent/atoms/std-agent-tool-call.orb +38 -2
- package/behaviors/registry/agent/atoms/std-agent-tool-loop.orb +38 -2
- package/behaviors/registry/agent/organisms/std-agent-rabit.orb +23 -1
- package/behaviors/registry/infra/atoms/std-approval-gate.orb +8 -16
- package/behaviors/registry/infra/atoms/std-cache-aside.orb +31 -62
- package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +16 -32
- package/behaviors/registry/infra/atoms/std-cross-reference.orb +32 -4
- package/behaviors/registry/infra/atoms/std-data-erasure.orb +8 -16
- package/behaviors/registry/infra/atoms/std-mod-queue.orb +8 -16
- package/behaviors/registry/infra/atoms/std-rate-limiter.orb +14 -28
- package/behaviors/registry/infra/atoms/std-row-access-control.orb +30 -2
- package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +1 -2
- package/behaviors/registry/ui/core/atoms/std-board.orb +19 -5
- package/behaviors/registry/ui/core/atoms/std-browse.orb +29 -7
- package/behaviors/registry/ui/core/atoms/std-dashboard-grid-embedded.orb +1 -2
- package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +3 -5
- package/behaviors/registry/ui/core/atoms/std-esign-request.orb +3 -6
- package/behaviors/registry/ui/core/atoms/std-event-log.orb +17 -3
- package/behaviors/registry/ui/core/atoms/std-export.orb +2 -4
- package/behaviors/registry/ui/core/atoms/std-form-advanced.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-gallery.orb +9 -18
- package/behaviors/registry/ui/core/atoms/std-graphs.orb +15 -1
- package/behaviors/registry/ui/core/atoms/std-import.orb +2 -4
- package/behaviors/registry/ui/core/atoms/std-list.orb +4 -6
- package/behaviors/registry/ui/core/atoms/std-modal.orb +2 -2
- package/behaviors/registry/ui/core/atoms/std-multi-party-flow.orb +16 -2
- package/behaviors/registry/ui/core/atoms/std-pagination.orb +15 -1
- package/behaviors/registry/ui/core/atoms/std-rating-review.orb +19 -5
- package/behaviors/registry/ui/core/atoms/std-recurrence.orb +17 -3
- package/behaviors/registry/ui/core/atoms/std-rich-editor.orb +15 -1
- package/behaviors/registry/ui/core/atoms/std-scatter.orb +15 -1
- package/behaviors/registry/ui/core/atoms/std-signature-capture.orb +2 -2
- package/behaviors/registry/ui/core/atoms/std-stats.orb +15 -1
- package/behaviors/registry/ui/core/atoms/std-step-flow.orb +16 -2
- package/behaviors/registry/ui/core/atoms/std-thread.orb +2 -2
- package/behaviors/registry/ui/core/atoms/std-vote.orb +2 -2
- package/behaviors/registry/ui/core/atoms/std-wizard.orb +17 -3
- package/behaviors/registry/ui/core/atoms/ui-atlas-image.orb +4 -1
- package/behaviors/registry/ui/core/atoms/ui-atlas-panel.orb +4 -1
- package/behaviors/registry/ui/core/atoms/ui-center.orb +4 -1
- package/behaviors/registry/ui/core/atoms/ui-hstack.orb +4 -1
- package/behaviors/registry/ui/core/atoms/ui-icon.orb +4 -1
- package/behaviors/registry/ui/core/atoms/ui-stack.orb +4 -1
- package/behaviors/registry/ui/core/atoms/ui-typography.orb +4 -1
- package/behaviors/registry/ui/core/atoms/ui-vstack.orb +4 -1
- package/behaviors/registry/ui/core/molecules/ui-accordion.orb +3 -3
- package/behaviors/registry/ui/core/molecules/ui-content-renderer.orb +4 -1
- package/behaviors/registry/ui/core/molecules/ui-form-layout.orb +4 -1
- package/behaviors/registry/ui/core/molecules/ui-grid.orb +4 -1
- package/behaviors/registry/ui/core/molecules/ui-tabs.orb +2 -2
- package/behaviors/registry/ui/core/molecules/ui-wizard-container.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-chat-bar.orb +4 -1
- package/behaviors/registry/ui/core/organisms/ui-dashboard-grid.orb +5 -2
- package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +5 -2
- package/behaviors/registry/ui/core/organisms/ui-entity-cards.orb +4 -1
- package/behaviors/registry/ui/core/organisms/ui-entity-list.orb +4 -1
- package/behaviors/registry/ui/core/organisms/ui-entity-table.orb +4 -1
- package/behaviors/registry/ui/core/organisms/ui-form-section.orb +34 -2
- package/behaviors/registry/ui/core/organisms/ui-form.orb +34 -2
- package/behaviors/registry/ui/core/organisms/ui-master-detail.orb +4 -1
- package/behaviors/registry/ui/core/organisms/ui-media-gallery.orb +4 -1
- package/behaviors/registry/ui/core/organisms/ui-segment-renderer.orb +24 -2
- package/behaviors/registry/ui/core/organisms/ui-stat-card.orb +4 -1
- package/behaviors/registry/ui/core/organisms/ui-subagent-trace-panel.orb +4 -1
- package/behaviors/registry/ui/core/organisms/ui-tabbed-container.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-ui-slot-renderer.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-fx-particles.orb +35 -1
- package/behaviors/registry/ui/game/atoms/ui-action-tile.orb +4 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-shape-layer.orb +183 -13
- package/behaviors/registry/ui/game/atoms/ui-draw-shape.orb +104 -9
- package/behaviors/registry/ui/game/atoms/ui-draw-sprite-layer.orb +56 -2
- package/behaviors/registry/ui/game/atoms/ui-draw-sprite.orb +36 -4
- package/behaviors/registry/ui/game/atoms/ui-draw-text-layer.orb +21 -2
- package/behaviors/registry/ui/game/atoms/ui-draw-text.orb +19 -4
- package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +173 -2
- package/behaviors/registry/ui/learning/atoms/std-learn-classify.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-compare.orb +2814 -0
- package/behaviors/registry/ui/learning/atoms/std-learn-coupled-sim.orb +3183 -0
- package/behaviors/registry/ui/learning/atoms/std-learn-estimate.orb +2394 -0
- package/behaviors/registry/ui/learning/atoms/std-learn-goal-seek.orb +3951 -0
- package/behaviors/registry/ui/learning/atoms/std-learn-grid-sim.orb +3458 -0
- package/behaviors/registry/ui/learning/atoms/std-learn-hotspot.orb +2646 -0
- package/behaviors/registry/ui/learning/atoms/std-learn-measure.orb +1979 -0
- package/behaviors/registry/ui/learning/atoms/std-learn-perturb.orb +2994 -0
- package/behaviors/registry/ui/learning/atoms/std-learn-predict.orb +2682 -0
- package/behaviors/registry/ui/learning/atoms/std-learn-scenario.orb +1842 -0
- package/behaviors/registry/ui/learning/atoms/std-learn-sim-3d.orb +1648 -0
- package/behaviors/registry/ui/learning/atoms/std-learn-speed-drill.orb +2307 -0
- package/behaviors/registry/ui/learning/atoms/std-learn-tour-3d.orb +2947 -0
- package/behaviors/registry/ui/learning/atoms/ui-algorithm-canvas.orb +173 -4
- package/behaviors/registry/ui/learning/atoms/ui-biology-canvas.orb +267 -7
- package/behaviors/registry/ui/learning/atoms/ui-chemistry-canvas.orb +263 -8
- package/behaviors/registry/ui/learning/atoms/ui-learning-canvas.orb +116 -1
- package/behaviors/registry/ui/learning/atoms/ui-math-canvas.orb +200 -4
- package/behaviors/registry/ui/learning/atoms/ui-physics-canvas.orb +264 -7
- package/behaviors/registry/ui/marketing/atoms/std-marketing-article.orb +1 -2
- package/behaviors/registry/ui/marketing/atoms/std-marketing-footer.orb +1 -2
- package/behaviors/registry/ui/marketing/atoms/std-marketing-split.orb +1 -2
- package/behaviors/registry/ui/marketing/atoms/std-marketing-stats.orb +1 -2
- package/behaviors/registry/ui/marketing/atoms/std-marketing-steps.orb +1 -2
- package/behaviors/registry/ui/marketing/atoms/std-marketing-team.orb +1 -2
- package/behaviors/registry/ui/marketing/organisms/ui-book-viewer.orb +4 -1
- package/behaviors/registry/ui/marketing/organisms/ui-case-study-organism.orb +4 -1
- package/behaviors/registry/ui/marketing/organisms/ui-feature-grid-organism.orb +4 -1
- package/behaviors/registry/ui/marketing/organisms/ui-hero-organism.orb +4 -1
- package/behaviors/registry/ui/marketing/organisms/ui-pricing-organism.orb +4 -1
- package/behaviors/registry/ui/marketing/organisms/ui-showcase-organism.orb +4 -1
- package/behaviors/registry/ui/marketing/organisms/ui-stats-organism.orb +4 -1
- package/behaviors/registry/ui/marketing/organisms/ui-step-flow-organism.orb +4 -1
- package/behaviors/registry/ui/marketing/organisms/ui-team-organism.orb +4 -1
- package/dist/behaviors/exports-reader.js +3440 -2189
- package/dist/behaviors/functions/index.d.ts +1751 -154
- package/dist/behaviors/functions/index.js +3402 -2190
- package/dist/behaviors/index.d.ts +1 -1
- package/dist/behaviors/index.js +3441 -2190
- package/dist/behaviors/query.js +3440 -2189
- package/dist/behaviors-embeddings.hash.json +3 -3
- package/dist/behaviors-embeddings.json +230 -178
- package/dist/behaviors-registry.json +4397 -171
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3441 -2190
- package/dist/knob-embeddings.hash.json +3 -3
- package/dist/knob-embeddings.json +1 -1
- package/dist/registry/factory-signatures.json +1 -1
- 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
|
+
}
|