@plasius/learning 0.4.0 → 0.6.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 (66) hide show
  1. package/README.md +28 -0
  2. package/dist/chunk-2UIOBMJZ.js +44 -0
  3. package/dist/chunk-2UIOBMJZ.js.map +1 -0
  4. package/dist/courses/beacon-bot.cjs +362 -0
  5. package/dist/courses/beacon-bot.cjs.map +1 -0
  6. package/dist/courses/beacon-bot.d.cts +6 -0
  7. package/dist/courses/beacon-bot.d.ts +6 -0
  8. package/dist/courses/beacon-bot.js +168 -0
  9. package/dist/courses/beacon-bot.js.map +1 -0
  10. package/dist/courses/dance-rover.cjs +374 -0
  11. package/dist/courses/dance-rover.cjs.map +1 -0
  12. package/dist/courses/dance-rover.d.cts +6 -0
  13. package/dist/courses/dance-rover.d.ts +6 -0
  14. package/dist/courses/dance-rover.js +180 -0
  15. package/dist/courses/dance-rover.js.map +1 -0
  16. package/dist/courses/meteor-shield.cjs +369 -0
  17. package/dist/courses/meteor-shield.cjs.map +1 -0
  18. package/dist/courses/meteor-shield.d.cts +6 -0
  19. package/dist/courses/meteor-shield.d.ts +6 -0
  20. package/dist/courses/meteor-shield.js +175 -0
  21. package/dist/courses/meteor-shield.js.map +1 -0
  22. package/dist/courses/obstacle-explorer.cjs +368 -0
  23. package/dist/courses/obstacle-explorer.cjs.map +1 -0
  24. package/dist/courses/obstacle-explorer.d.cts +6 -0
  25. package/dist/courses/obstacle-explorer.d.ts +6 -0
  26. package/dist/courses/obstacle-explorer.js +174 -0
  27. package/dist/courses/obstacle-explorer.js.map +1 -0
  28. package/dist/courses/pixel-trail-challenge.cjs +366 -0
  29. package/dist/courses/pixel-trail-challenge.cjs.map +1 -0
  30. package/dist/courses/pixel-trail-challenge.d.cts +6 -0
  31. package/dist/courses/pixel-trail-challenge.d.ts +6 -0
  32. package/dist/courses/pixel-trail-challenge.js +172 -0
  33. package/dist/courses/pixel-trail-challenge.js.map +1 -0
  34. package/dist/courses/rainbow-rescue-rover.cjs +377 -0
  35. package/dist/courses/rainbow-rescue-rover.cjs.map +1 -0
  36. package/dist/courses/rainbow-rescue-rover.d.cts +6 -0
  37. package/dist/courses/rainbow-rescue-rover.d.ts +6 -0
  38. package/dist/courses/rainbow-rescue-rover.js +183 -0
  39. package/dist/courses/rainbow-rescue-rover.js.map +1 -0
  40. package/dist/courses/rescue-crew-commander.cjs +369 -0
  41. package/dist/courses/rescue-crew-commander.cjs.map +1 -0
  42. package/dist/courses/rescue-crew-commander.d.cts +6 -0
  43. package/dist/courses/rescue-crew-commander.d.ts +6 -0
  44. package/dist/courses/rescue-crew-commander.js +175 -0
  45. package/dist/courses/rescue-crew-commander.js.map +1 -0
  46. package/dist/courses/robot-maze-dash.js +3 -38
  47. package/dist/courses/robot-maze-dash.js.map +1 -1
  48. package/dist/courses/servo-creature.cjs +369 -0
  49. package/dist/courses/servo-creature.cjs.map +1 -0
  50. package/dist/courses/servo-creature.d.cts +6 -0
  51. package/dist/courses/servo-creature.d.ts +6 -0
  52. package/dist/courses/servo-creature.js +175 -0
  53. package/dist/courses/servo-creature.js.map +1 -0
  54. package/dist/courses/skywing-sprint.cjs +367 -0
  55. package/dist/courses/skywing-sprint.cjs.map +1 -0
  56. package/dist/courses/skywing-sprint.d.cts +6 -0
  57. package/dist/courses/skywing-sprint.d.ts +6 -0
  58. package/dist/courses/skywing-sprint.js +173 -0
  59. package/dist/courses/skywing-sprint.js.map +1 -0
  60. package/dist/courses/star-defender-squadron.cjs +369 -0
  61. package/dist/courses/star-defender-squadron.cjs.map +1 -0
  62. package/dist/courses/star-defender-squadron.d.cts +6 -0
  63. package/dist/courses/star-defender-squadron.d.ts +6 -0
  64. package/dist/courses/star-defender-squadron.js +175 -0
  65. package/dist/courses/star-defender-squadron.js.map +1 -0
  66. package/package.json +51 -1
@@ -0,0 +1,6 @@
1
+ import { L as LearningCourseV1, C as CoursePracticeQuestion } from '../course-authoring-DImvrK5r.cjs';
2
+
3
+ declare const course: LearningCourseV1;
4
+ declare const practice: CoursePracticeQuestion[];
5
+
6
+ export { course, practice };
@@ -0,0 +1,6 @@
1
+ import { L as LearningCourseV1, C as CoursePracticeQuestion } from '../course-authoring-DImvrK5r.js';
2
+
3
+ declare const course: LearningCourseV1;
4
+ declare const practice: CoursePracticeQuestion[];
5
+
6
+ export { course, practice };
@@ -0,0 +1,175 @@
1
+ import {
2
+ authorCourse
3
+ } from "../chunk-2UIOBMJZ.js";
4
+ import "../chunk-OXWMIHYI.js";
5
+
6
+ // src/courses/servo-creature.ts
7
+ var { course, practice } = authorCourse({
8
+ slug: "servo-creature",
9
+ title: "Servo Creature",
10
+ category: "robot",
11
+ summary: "Give a simulated creature a moving joint and a personality. Begin with safe angle limits, add smooth motion and reusable pose sequences, then respond to mood requests and touch. Finish a small creature show whose stop and proximity rules remain effective throughout. Physical hardware is not required.",
12
+ projectFiles: [{ path: "robot.cpp", language: "cpp", maximumCharacters: 24e3 }],
13
+ starterProject: { files: [{ path: "robot.cpp", source: `double angle = 90;
14
+ int lastTime = 0;
15
+
16
+ void setup() {
17
+ setServoEnabled(false);
18
+ setCreatureMood("calm");
19
+ lastTime = millis();
20
+ }
21
+
22
+ void loop() {
23
+ lastTime = millis();
24
+ setServoEnabled(false);
25
+ }
26
+ ` }] },
27
+ reference: [
28
+ { name: "setServoEnabled", signature: "setServoEnabled(bool enabled)", description: "Enable or disable the simulated joint. Disabled holds the last actual angle; do not send angle commands while disabled. Stop or an unsafe proximity reading must disable the joint before other movement decisions.", example: 'if (boolSensor("stop")) { setServoEnabled(false); return; }' },
29
+ { name: "setServoAngle", signature: "setServoAngle(double degrees)", description: "Request an enabled joint angle from 30 through 150 degrees. The joint starts at 90. The simulator rejects out-of-range commands; later missions also require the learner's source to limit movement to 45 degrees per simulated second.", example: "double bounded = max(30.0, min(150.0, requested));" },
30
+ { name: "millis", signature: "int millis()", description: "Read supplied simulated time. Derive elapsed seconds with division by 1000.0 and cap a control step at 0.1 seconds. Update lastTime even while stopped so resuming does not accumulate an old delay into a sudden jump.", example: "double dt = min(0.1, (millis() - lastTime) / 1000.0); lastTime = millis();" },
31
+ { name: "approach", signature: "double approach(double current, double target, double step)", description: "A learner-authored helper moves toward the target by at most step and stops exactly on arrival. It must work from above or below without overshooting or changing the permitted angle range.", example: "if (current < target) return min(target, current + step); return max(target, current - step);" },
32
+ { name: "setCreatureMood", signature: "setCreatureMood(string mood)", description: "Choose calm, curious or happy, presented with text and a distinct symbol. The mood affects the chosen target pose, not the angle bounds or stop protections. Unknown requests use calm.", example: 'setCreatureMood("curious");' },
33
+ { name: "mood requests", signature: 'textSensor("requestedMood"); numberSensor("moodRequestId");', description: "A supplied integer request id identifies a new mood selection. Handle a new request once; repeated observations of its id must not override later touch-driven changes. A new request takes priority over a simultaneous touch edge.", example: 'int requestId = numberSensor("moodRequestId"); if (requestId != lastRequestId) { lastRequestId = requestId; }' },
34
+ { name: "touch and proximity", signature: 'boolSensor("touch"); numberSensor("distanceCm");', description: "Use a rising touch edge to cycle moods once. A distance below 10 cm, below zero or above 400 is unsafe for this simulator and disables motion. Read these observations freshly; update touch history while stopped.", example: 'bool touched = boolSensor("touch"); bool rising = touched && !wasTouched; wasTouched = touched;' },
35
+ { name: "pose sequence", signature: "double poseForPhase(int phase)", description: "The sequence uses 60, 120 and 90 degrees for phases zero, one and two, with 2000 ms between phase changes. Smoothing approaches each target. Stop holds the phase and refreshes its clock; restarting the simulator starts the sequence again.", example: "phase = (phase + 1) % 3;" }
36
+ ]
37
+ }, [
38
+ {
39
+ title: "A pose inside the limits",
40
+ concepts: ["Angles", "Bounds", "Enabled state"],
41
+ goals: ["Move an enabled simulated joint only within its 30\u2013150 degree range.", "Keep startup disabled and make stop hold the joint's current angle."],
42
+ extension: "Sketch three poses inside the permitted range and label their angles. Explain why a more dramatic pose cannot justify sending an out-of-range command.",
43
+ activities: {
44
+ learn: ["The creature's joint starts at 90 degrees and may move from 30 to 150. A requested pose and permission to move are separate decisions. Keep setup disabled; while active enable the joint before setting an angle. Stop disables it and holds the last actual pose.", "This is a simulator. These teaching limits are not instructions for attaching or powering a real servo."],
45
+ predict: ["Predict which requests among 20, 30, 90, 150 and 170 degrees are permitted. Then stop the creature at 120 and decide whether stop should force a sudden move back to 90.", "Disabling holds the current angle. Neutral position is a target pose, not an automatic consequence of stop."],
46
+ build: ["Keep the safe setup and edit loop to check stop first. Otherwise enable the joint and request a bounded 120-degree pose. Use min and max to express the allowed range if the target comes from a variable.", "Do not set an angle after disabling. An early return makes the priority stop branch explicit."],
47
+ run: ["Run the creature and inspect its angle and enabled state. Stop it at the selected pose using keyboard and onscreen controls. Compare the joint picture with the numeric angle and status label.", "The text state explains enabled and disabled without relying on movement alone."],
48
+ assess: ["Check disabled startup, valid boundary angles, rejected out-of-range requests and stop priority. The evaluator distinguishes an enabled angle command from one sent while the joint should be held.", "A clamped display cannot repair unsafe source commands. The project itself must request values within the documented range."],
49
+ inspect: ["If the creature moves during stop, inspect command order and early return. If it refuses a pose, inspect bounds and whether enabling happened first. If the label changes but the joint does not, compare emitted commands with the enabled state.", "Treat the command trace as evidence of what the programme requested, separate from the picture's presentation."],
50
+ fix: ["Repair enabling or bounds, then test 30, 90 and 150 as valid values and a stopped observation. Preserve the stopped actual angle and verify the next active observation can still select a valid pose.", "Do not remove stop handling to make the joint move; repair the valid active path."],
51
+ explain: ["Choose why permission to move is separate from the requested angle. Explain why holding the last pose can be a clearer stopped behaviour than unexpectedly jumping to a neutral position.", "A safe state transition should have one documented meaning that remains visible in the status text."],
52
+ reward: ["Save Bounded pose. You have a clear joint range and a priority stop path. Next you will approach a target gradually so the creature moves smoothly rather than jumping between poses.", "Keep these boundary-angle cases for every later movement change."]
53
+ },
54
+ questions: {
55
+ learn: { question: "Which range is permitted for this simulated joint?", choices: ["Any angle at all", "30 through 150 degrees", "Only values above 180"], correctChoice: 1, feedback: "The documented teaching range includes both endpoints, with 90 degrees as the initial pose." },
56
+ predict: { question: "Stop is pressed while the joint is at 120 degrees; what should happen?", choices: ["Jump immediately to zero", "Keep moving to the next phase", "Disable and hold the current angle"], correctChoice: 2, feedback: "Stop disables motion and preserves the actual pose instead of introducing an unexpected movement." },
57
+ explain: { question: "Why track enabled state separately from target angle?", choices: ["A valid pose is not itself permission to move", "It removes the need for angle bounds", "It changes the device into a real robot"], correctChoice: 0, feedback: "The project must satisfy both the movement permission and the range rule before applying a pose." }
58
+ }
59
+ },
60
+ {
61
+ title: "Move a little at a time",
62
+ concepts: ["Rate limits", "Floating arithmetic", "Arrival clamping"],
63
+ goals: ["Approach a target at no more than 45 degrees per simulated second.", "Avoid overshoot and accumulated movement after a long stopped interval."],
64
+ extension: "Compare approach speeds 20 and 45 using the same target and observations. Explain how speed affects travel time while the final pose remains unchanged.",
65
+ activities: {
66
+ learn: ["Smooth motion changes angle by a bounded amount each observation. Compute dt=(now-lastTime)/1000.0, cap dt at 0.1 and use step=45\xD7dt. Move toward the target by at most that step, clamping at arrival. Store angle and lastTime globally.", "The decimal 1000.0 matters: integer division could make short elapsed intervals become zero."],
67
+ predict: ["At 45 degrees per second and dt=0.02, predict the maximum change. If the remaining gap is only 0.3 degrees, decide whether to apply the whole normal step. Consider a long stopped interval before resuming.", "The ordinary step is 0.9 degrees, but a closer target needs only its remaining gap. Refresh time while stopped to prevent a large resume step."],
68
+ build: ["Write approach(current,target,step) as a double helper using min below the target and max above it. Update lastTime on every observation, including stop. While enabled, update the global angle through approach and emit that bounded value.", "Calculate elapsed time before replacing lastTime; replacing it first would make every dt zero."],
69
+ run: ["Step from 90 toward 120, then toward 60. Inspect consecutive angle differences and the final short arrival step. Stop for several observations, resume and confirm there is no sudden catch-up jump.", "Use the numeric trace to inspect smoothness even when reduced motion keeps the preview still."],
70
+ assess: ["Check both directions, exact arrival, small and large elapsed intervals, int-versus-double division and stop/resume timing. Requested angle changes must obey the 45-degree rate and remain within bounds.", "A slow-looking animation cannot prove correct rate limiting; the checks compare successive commanded values and simulated time."],
71
+ inspect: ["If nothing moves, inspect integer division and timestamp order. If it overshoots, inspect arrival clamping. If resuming jumps, inspect whether stopped observations still refresh lastTime.", "Separate current angle, target, elapsed seconds and allowed step while debugging the calculation."],
72
+ fix: ["Repair the calculation and replay the short-gap, reverse-direction and stopped-interval cases. Recheck enabled state and angle limits from the first mission so smoothing cannot bypass them.", "A new target does not permit a larger instantaneous step; the same approach rule applies in either direction."],
73
+ explain: ["Choose why the final step must be clamped to the target even when the rate is correct. Explain why simulated seconds and floating arithmetic belong together in this control loop.", "A rate describes how far movement may progress, not a requirement to overshoot a nearby destination."],
74
+ reward: ["Save Gentle movement. Your creature now reaches poses smoothly and resumes predictably. Next you will organise several target poses into a reusable timed sequence.", "Keep the 0.3-degree arrival case because it exposes a subtle overshoot error."]
75
+ },
76
+ questions: {
77
+ learn: { question: "Why divide elapsed milliseconds by 1000.0 rather than integer 1000?", choices: ["To make every interval ten seconds", "To ignore elapsed time", "To retain fractional seconds in short updates"], correctChoice: 2, feedback: "Floating division preserves small intervals such as 0.02 seconds instead of truncating them to zero." },
78
+ predict: { question: "At 45 degrees per second, what is the maximum change in 0.02 seconds?", choices: ["0.9 degrees", "45 degrees", "900 degrees"], correctChoice: 0, feedback: "The rate multiplied by elapsed seconds is 45 \xD7 0.02 = 0.9 degrees." },
79
+ explain: { question: "Why refresh lastTime even during a stopped observation?", choices: ["To secretly move while stopped", "To prevent old stopped time becoming a large resume movement", "To erase the target"], correctChoice: 1, feedback: "The timestamp tracks the latest observation, so resuming does not treat the whole stopped period as one movement step." }
80
+ }
81
+ },
82
+ {
83
+ title: "A sequence of poses",
84
+ concepts: ["Parameters", "Timed phases", "Separation of concerns"],
85
+ goals: ["Map three timed phases to target poses through one reusable helper.", "Keep target selection separate from the smooth movement and stop rules."],
86
+ extension: "Design a second sequence by changing only its target mapping. Keep the movement rate and phase interval unchanged so the comparison has one clear cause.",
87
+ activities: {
88
+ learn: ["A sequence selects targets; the approach helper moves toward them. Define poseForPhase with 60, 120 and 90 degrees for phases zero, one and two. Advance the phase every 2000 ms using modulo three. Each target still passes through the same smooth movement rule.", "Do not send the new target directly on a phase change, or the sequence will bypass smoothing exactly when it matters."],
89
+ predict: ["Starting at phase two, predict the next phase and target. Then compare changing a target to 120 with instantly commanding angle 120 while the current pose is 60.", "The target can change immediately while the actual angle approaches it over several observations."],
90
+ build: ["Add a phase variable, phase timestamp and poseForPhase helper. Update the phase only when the two-second interval elapses. During stop hold the phase and refresh its clock, then feed the current target to approach while active.", "Keep phase time distinct from lastTime used for movement steps; the two clocks represent different intervals."],
91
+ run: ["Step through two full sequences, pausing at a phase boundary. Watch target and current angle separately. Stop during the middle phase and resume to confirm the sequence does not skip ahead through the stopped time.", "A trace with phase, target and angle explains the sequence even without watching an animated joint."],
92
+ assess: ["Check all target mappings, wraparound, phase interval, held phase during stop and bounded movement on target changes. An unexpected phase should return the neutral 90-degree target.", "The helper must use its parameter so it can be checked independently of the live global phase."],
93
+ inspect: ["If target changes move instantly, inspect where approach is bypassed. If phases skip after stop, inspect the phase timestamp. If every phase uses one pose, inspect the helper's parameter comparisons.", "Test target selection separately from movement to find which part of the sequence is wrong."],
94
+ fix: ["Repair phase selection or timing and replay a full cycle plus a stop at a boundary. Preserve the movement-rate and enabled-state checks from earlier missions.", "Changing a sequence should not require rewriting the safe movement calculation."],
95
+ explain: ["Choose why target selection and movement belong in separate helpers. Explain how the same approach rule can support another sequence without repeating its safety logic.", "Separate responsibilities let one function decide where to go and another decide how far it may move now."],
96
+ reward: ["Save Living sequence. Your creature can perform a repeated set of smooth poses. Next you will give different target choices meaningful mood names and symbols.", "Keep the neutral fallback case when adding any new pose mappings."]
97
+ },
98
+ questions: {
99
+ learn: { question: "What should a phase change alter immediately?", choices: ["The selected target, while movement still approaches it", "Every safety limit", "The actual angle regardless of distance"], correctChoice: 0, feedback: "Selecting another target does not bypass the bounded approach used to move the joint." },
100
+ predict: { question: "Which phase and target follow phase two in the documented sequence?", choices: ["Phase three at 180", "Phase zero at 60", "Phase two forever"], correctChoice: 1, feedback: "Modulo three wraps the next phase back to zero, whose target is 60 degrees." },
101
+ explain: { question: "Why keep phase timing separate from the movement-step timestamp?", choices: ["To prevent all timing", "To make stop delay longer", "They measure different intervals and responsibilities"], correctChoice: 2, feedback: "One clock schedules target changes, while the other limits movement during each individual observation." }
102
+ }
103
+ },
104
+ {
105
+ title: "Give the creature a mood",
106
+ concepts: ["Named modes", "Input identity", "Fallbacks"],
107
+ goals: ["Map calm, curious and happy requests to clear mood labels and target poses.", "Handle each new request once and use a safe fallback for unknown mood text."],
108
+ extension: "Propose another mood with a text label, symbol and bounded target. Explain how it would fit the existing mapping and which checks would need extending.",
109
+ activities: {
110
+ learn: ["A mood names a mode of behaviour. Map calm to a 90-degree target, curious to 120 and happy to 60, and emit the matching mood label. A moodRequestId identifies a new selection; repeated observations of the same request are not new instructions. Unknown mood text falls back to calm.", "The mode changes the target choice, not the angle bounds, movement rate or stop priority."],
111
+ predict: ["A curious request with id four arrives twice. Predict how many selection events it represents. Then an unknown mood arrives with id five; choose the target and label that should follow.", "Identity distinguishes a repeated observation from a new request, while validation decides whether the requested value is supported."],
112
+ build: ["Store mood and lastRequestId globally. On a new request id, validate requestedMood and select calm, curious or happy once. Add a helper that returns the mood target and pass that target through approach. Keep the sequence helper available as a separate exercise.", "Do not replace the current mood on every repeated observation, because a later touch event will also be able to change it."],
113
+ run: ["Select each mood with keyboard and onscreen controls. Inspect its label, symbol, target and actual approach. Repeat a request id and send an unknown value to compare identity handling with fallback handling.", "Meaning should remain clear from words and symbols even when the joint is paused or disabled."],
114
+ assess: ["Check all three mappings, repeated ids, a new invalid request and smooth movement toward a changed target. Tests require the unknown request to use calm without losing the safe control state.", "A new id is not proof that its text is valid. Apply both checks."],
115
+ inspect: ["If a repeated request keeps undoing another change, inspect lastRequestId. If a mood changes safety bounds, separate the mapping from control limits. If unknown text causes an arbitrary pose, inspect the fallback branch.", "Trace request id, requested text and accepted mood as three distinct values."],
116
+ fix: ["Repair request handling or mapping and repeat valid, duplicate and unknown selections. Recheck movement rate during a large target change and stop while a request arrives.", "A safe fallback should still leave the creature usable and explain which supported mood was selected."],
117
+ explain: ["Choose why a named mood can change expression without changing safety rules. Explain why repeated sensor records need identity when several kinds of interaction can change the same state.", "The interface describes intent; the control loop still enforces what motion is permitted."],
118
+ reward: ["Save Expressive creature. Your joint now has understandable modes driven by explicit requests. Next it will react once to touch and stop when a proximity observation makes movement unsafe.", "Keep a repeated request as a regression case when adding another input source."]
119
+ },
120
+ questions: {
121
+ learn: { question: "What should remain unchanged when the creature's mood changes?", choices: ["Only its text label", "Angle, movement-rate and stop protections", "The previous request id forever"], correctChoice: 1, feedback: "Mood chooses an expression target; the shared control limits and stop priority remain in force." },
122
+ predict: { question: "A new request contains an unknown mood; which documented fallback is used?", choices: ["An angle outside the range", "A random mood each frame", "Calm with a 90-degree target"], correctChoice: 2, feedback: "Unknown text has a predictable supported fallback, keeping both presentation and movement understandable." },
123
+ explain: { question: "Why remember the last mood request id?", choices: ["To process one request once instead of replaying the same observation", "To remove touch support", "To bypass text validation"], correctChoice: 0, feedback: "Identity prevents repeated observations from continually reapplying an old selection after other interactions." }
124
+ }
125
+ },
126
+ {
127
+ title: "A gentle response to touch",
128
+ concepts: ["Input edges", "Safety priority", "Fresh observations"],
129
+ goals: ["Cycle moods once for each new touch while handling held input predictably.", "Disable movement for unsafe proximity and preserve input/time history through stop."],
130
+ extension: "Build a timeline of touch, hold, release and a nearby obstacle. Explain which observations change mood and which require holding the joint still.",
131
+ activities: {
132
+ learn: ["A new touch is touched&&!wasTouched, so a held sensor does not cycle moods repeatedly. Read distance fresh: values below 10 cm, below zero or above 400 disable the joint. Update touch history and timestamps even when movement is disabled, then return before sending angles.", "A sensor's reading is an observation, not a permanent promise that the space will remain clear."],
133
+ predict: ["Predict mood changes for false, true, true, false, true touch observations. Then hold touch while distance falls to five centimetres and later becomes clear: decide whether clearing the obstacle alone should create another touch event.", "Only a real false-to-true transition creates a new touch. Safety recovery must not invent an input edge."],
134
+ build: ["Add wasTouched and edge detection. Cycle calm to curious to happy to calm on a valid new touch. Give a new explicit mood request priority over a simultaneous edge. Apply stop and proximity guards before enabling or commanding the joint.", "Consume observation history while disabled, but do not move or apply a delayed old touch on resume."],
135
+ run: ["Use touch controls, hold through several observations and then release. Introduce near, invalid and clear distance readings while stepping. Inspect enabled state, actual angle, mood and previous-touch history together.", "The simulator offers supplied distance values; it does not request a physical sensor or camera connection."],
136
+ assess: ["Check touch edges, long holds, simultaneous request priority, stop, near and invalid distances, and safe recovery. Failed or mistyped sensor input must result in a stopped simulation rather than continued motion.", "A correct normal touch response does not establish that the priority safety branches work."],
137
+ inspect: ["If a hold changes mood repeatedly, inspect edge history. If a nearby obstacle is ignored, inspect fresh sensor reads and branch order. If resume jumps, inspect time updates during disabled observations.", "Look for the earliest observation where accepted input or enabled state differs from the documented rule."],
138
+ fix: ["Repair the input or safety branch and replay hold-through-stop and hold-through-near-obstacle cases. Confirm a later genuine new touch still works and every commanded angle remains bounded and smooth.", "Keep old input from replaying, while preserving useful future interaction after the space becomes clear."],
139
+ explain: ["Choose why safety observations take priority over expression. Explain how updating input history while disabled supports a predictable recovery without secretly moving the joint.", "Maintaining state and commanding movement are separate operations; the first can continue while the second is disabled."],
140
+ reward: ["Save Gentle reactions. Your creature now responds to deliberate touch and fresh safety observations. The final show integrates its expression, smooth motion and priority stop behaviour.", "Keep the simultaneous-request-and-touch case because it makes interaction priority explicit."]
141
+ },
142
+ questions: {
143
+ learn: { question: "What should happen when the supplied distance is five centimetres?", choices: ["Continue the show unchanged", "Speed up to move away blindly", "Disable the joint and hold its current pose"], correctChoice: 2, feedback: "The simulator's near-object rule stops motion before expression logic can issue another angle command." },
144
+ predict: { question: "Touch stays held while an obstacle appears and clears; does clearing create a new touch?", choices: ["No, the touch state never made a new rising edge", "Yes, every clear reading is a touch", "Yes, stop erases all input history"], correctChoice: 0, feedback: "Maintained touch history distinguishes a continuing hold from a new intentional press after release." },
145
+ explain: { question: "Which input wins when a new mood request and a touch edge arrive together?", choices: ["Both in an unspecified order", "The new explicit mood request", "Neither, and the joint must jump"], correctChoice: 1, feedback: "The documented priority applies the explicit selection once, avoiding two conflicting changes in one observation." }
146
+ }
147
+ },
148
+ {
149
+ title: "The creature show",
150
+ concepts: ["Integration", "Interaction priority", "Regression evidence"],
151
+ goals: ["Present a complete responsive creature with named expression and smooth bounded movement.", "Preserve stop, proximity, request identity and touch-edge rules throughout the show and restart."],
152
+ extension: "Design a new expression sequence in a separate save. State its intended mood and replay the existing range, rate, stop and input-boundary checks before comparing it with the finished show.",
153
+ activities: {
154
+ learn: ["A finished creature combines understandable expression with a reliable controller. Keep one order: read fresh inputs, update time and touch history, apply safety guards, accept a new request or touch edge, choose a target and approach it. The sequence exercise can reuse the same movement helper.", "The same safety controller should support both a pose sequence and an interactive mood demonstration."],
155
+ predict: ["Predict a show observation with a new happy request, a touch edge and stop true. Then release stop without releasing touch and consider a later genuine new request. Identify which state may update and which movement is forbidden.", "Stop prevents movement regardless of expression input. Updated history prevents an old held touch from replaying on recovery."],
156
+ build: ["Combine the verified helpers into the interactive show, retaining a separately named sequence helper for replay. Keep control state explicit and use one bounded movement path. Restart with a fresh session at 90 degrees, disabled, calm and with fresh timing history.", "Do not let a new feature issue angle commands through another path that bypasses the shared checks."],
157
+ run: ["Demonstrate each mood using keyboard and touch controls, then run the pose sequence exercise. Pause, stop, introduce a near reading, recover and restart. Compare status text, symbols, target and actual angle in reduced-motion mode.", "A complete demonstration should remain understandable without watching every movement."],
158
+ assess: ["Assess the saved final project across target changes, short and delayed observations, duplicate requests, held touch, simultaneous inputs, proximity and stop. Check the earlier pose helper as well as the interactive controller.", "The capstone verifies the integrated rules, not merely whether the creature reaches one attractive final pose."],
159
+ inspect: ["Locate the first incorrect command in a failing trace and identify which priority or bound allowed it. Separate target-selection errors from motion-rate errors and input-history errors before choosing a repair.", "A correct final angle can hide an unsafe intermediate jump; inspect the full commanded sequence."],
160
+ fix: ["Repair the controller and rerun the focused failure plus earlier bounds, arrival, sequence and touch cases. Save and assess the exact new source before finishing, keeping a stable named version for later experiments.", "Do not hide an overspeed command by slowing only the animation. Repair the values the programme emits."],
161
+ explain: ["Choose what makes the creature show predictable and describe how one extension could affect existing rules. Explain the distinction between this supplied-input simulator and an independently approved physical build.", "The project demonstrates programming evidence; it does not grant permission to connect or operate equipment."],
162
+ reward: ["Save Creature show and complete the final assessment. You have built a responsive simulated character with reusable functions, smooth motion and explicit input priorities. Replay missions or experiment in another named save while retaining earned completion.", "Keep the tested version before extending the show. Existing guardian and hardware protections remain separate from completing the simulator."]
163
+ },
164
+ questions: {
165
+ learn: { question: "Where should every angle command pass before reaching the simulated joint?", choices: ["Through the shared safety and bounded movement rules", "Through whichever mood branch runs last", "Directly from any unvalidated sensor string"], correctChoice: 0, feedback: "A single shared control path keeps new expressions from bypassing range, rate and stop requirements." },
166
+ predict: { question: "A happy request and touch arrive while stop is true; may the joint move?", choices: ["Yes, because two inputs arrived", "No, stop retains priority over expression", "Only beyond the normal angle limits"], correctChoice: 1, feedback: "Expression inputs do not override the movement guard. The stopped controller holds its actual pose." },
167
+ explain: { question: "What does passing the creature simulator's final checks establish?", choices: ["Automatic approval for any real servo build", "That future source changes need no checks", "Evidence that the documented simulated controller behaves correctly"], correctChoice: 2, feedback: "The assessment covers the supplied simulator scenarios; physical equipment and future changes require their own appropriate checks." }
168
+ }
169
+ }
170
+ ]);
171
+ export {
172
+ course,
173
+ practice
174
+ };
175
+ //# sourceMappingURL=servo-creature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/courses/servo-creature.ts"],"sourcesContent":["import { authorCourse } from \"./course-authoring.js\";\n\nexport const { course, practice } = authorCourse({\n slug: \"servo-creature\", title: \"Servo Creature\", category: \"robot\",\n summary: \"Give a simulated creature a moving joint and a personality. Begin with safe angle limits, add smooth motion and reusable pose sequences, then respond to mood requests and touch. Finish a small creature show whose stop and proximity rules remain effective throughout. Physical hardware is not required.\",\n projectFiles: [{ path: \"robot.cpp\", language: \"cpp\", maximumCharacters: 24000 }],\n starterProject: { files: [{ path: \"robot.cpp\", source: `double angle = 90;\nint lastTime = 0;\n\nvoid setup() {\n setServoEnabled(false);\n setCreatureMood(\"calm\");\n lastTime = millis();\n}\n\nvoid loop() {\n lastTime = millis();\n setServoEnabled(false);\n}\n` }] },\n reference: [\n { name: \"setServoEnabled\", signature: \"setServoEnabled(bool enabled)\", description: \"Enable or disable the simulated joint. Disabled holds the last actual angle; do not send angle commands while disabled. Stop or an unsafe proximity reading must disable the joint before other movement decisions.\", example: 'if (boolSensor(\"stop\")) { setServoEnabled(false); return; }' },\n { name: \"setServoAngle\", signature: \"setServoAngle(double degrees)\", description: \"Request an enabled joint angle from 30 through 150 degrees. The joint starts at 90. The simulator rejects out-of-range commands; later missions also require the learner's source to limit movement to 45 degrees per simulated second.\", example: \"double bounded = max(30.0, min(150.0, requested));\" },\n { name: \"millis\", signature: \"int millis()\", description: \"Read supplied simulated time. Derive elapsed seconds with division by 1000.0 and cap a control step at 0.1 seconds. Update lastTime even while stopped so resuming does not accumulate an old delay into a sudden jump.\", example: \"double dt = min(0.1, (millis() - lastTime) / 1000.0); lastTime = millis();\" },\n { name: \"approach\", signature: \"double approach(double current, double target, double step)\", description: \"A learner-authored helper moves toward the target by at most step and stops exactly on arrival. It must work from above or below without overshooting or changing the permitted angle range.\", example: \"if (current < target) return min(target, current + step); return max(target, current - step);\" },\n { name: \"setCreatureMood\", signature: \"setCreatureMood(string mood)\", description: \"Choose calm, curious or happy, presented with text and a distinct symbol. The mood affects the chosen target pose, not the angle bounds or stop protections. Unknown requests use calm.\", example: 'setCreatureMood(\"curious\");' },\n { name: \"mood requests\", signature: 'textSensor(\"requestedMood\"); numberSensor(\"moodRequestId\");', description: \"A supplied integer request id identifies a new mood selection. Handle a new request once; repeated observations of its id must not override later touch-driven changes. A new request takes priority over a simultaneous touch edge.\", example: 'int requestId = numberSensor(\"moodRequestId\"); if (requestId != lastRequestId) { lastRequestId = requestId; }' },\n { name: \"touch and proximity\", signature: 'boolSensor(\"touch\"); numberSensor(\"distanceCm\");', description: \"Use a rising touch edge to cycle moods once. A distance below 10 cm, below zero or above 400 is unsafe for this simulator and disables motion. Read these observations freshly; update touch history while stopped.\", example: 'bool touched = boolSensor(\"touch\"); bool rising = touched && !wasTouched; wasTouched = touched;' },\n { name: \"pose sequence\", signature: \"double poseForPhase(int phase)\", description: \"The sequence uses 60, 120 and 90 degrees for phases zero, one and two, with 2000 ms between phase changes. Smoothing approaches each target. Stop holds the phase and refreshes its clock; restarting the simulator starts the sequence again.\", example: \"phase = (phase + 1) % 3;\" },\n ],\n}, [\n {\n title: \"A pose inside the limits\", concepts: [\"Angles\", \"Bounds\", \"Enabled state\"],\n goals: [\"Move an enabled simulated joint only within its 30–150 degree range.\", \"Keep startup disabled and make stop hold the joint's current angle.\"],\n extension: \"Sketch three poses inside the permitted range and label their angles. Explain why a more dramatic pose cannot justify sending an out-of-range command.\",\n activities: {\n learn: [\"The creature's joint starts at 90 degrees and may move from 30 to 150. A requested pose and permission to move are separate decisions. Keep setup disabled; while active enable the joint before setting an angle. Stop disables it and holds the last actual pose.\", \"This is a simulator. These teaching limits are not instructions for attaching or powering a real servo.\"],\n predict: [\"Predict which requests among 20, 30, 90, 150 and 170 degrees are permitted. Then stop the creature at 120 and decide whether stop should force a sudden move back to 90.\", \"Disabling holds the current angle. Neutral position is a target pose, not an automatic consequence of stop.\"],\n build: [\"Keep the safe setup and edit loop to check stop first. Otherwise enable the joint and request a bounded 120-degree pose. Use min and max to express the allowed range if the target comes from a variable.\", \"Do not set an angle after disabling. An early return makes the priority stop branch explicit.\"],\n run: [\"Run the creature and inspect its angle and enabled state. Stop it at the selected pose using keyboard and onscreen controls. Compare the joint picture with the numeric angle and status label.\", \"The text state explains enabled and disabled without relying on movement alone.\"],\n assess: [\"Check disabled startup, valid boundary angles, rejected out-of-range requests and stop priority. The evaluator distinguishes an enabled angle command from one sent while the joint should be held.\", \"A clamped display cannot repair unsafe source commands. The project itself must request values within the documented range.\"],\n inspect: [\"If the creature moves during stop, inspect command order and early return. If it refuses a pose, inspect bounds and whether enabling happened first. If the label changes but the joint does not, compare emitted commands with the enabled state.\", \"Treat the command trace as evidence of what the programme requested, separate from the picture's presentation.\"],\n fix: [\"Repair enabling or bounds, then test 30, 90 and 150 as valid values and a stopped observation. Preserve the stopped actual angle and verify the next active observation can still select a valid pose.\", \"Do not remove stop handling to make the joint move; repair the valid active path.\"],\n explain: [\"Choose why permission to move is separate from the requested angle. Explain why holding the last pose can be a clearer stopped behaviour than unexpectedly jumping to a neutral position.\", \"A safe state transition should have one documented meaning that remains visible in the status text.\"],\n reward: [\"Save Bounded pose. You have a clear joint range and a priority stop path. Next you will approach a target gradually so the creature moves smoothly rather than jumping between poses.\", \"Keep these boundary-angle cases for every later movement change.\"],\n },\n questions: {\n learn: { question: \"Which range is permitted for this simulated joint?\", choices: [\"Any angle at all\", \"30 through 150 degrees\", \"Only values above 180\"], correctChoice: 1, feedback: \"The documented teaching range includes both endpoints, with 90 degrees as the initial pose.\" },\n predict: { question: \"Stop is pressed while the joint is at 120 degrees; what should happen?\", choices: [\"Jump immediately to zero\", \"Keep moving to the next phase\", \"Disable and hold the current angle\"], correctChoice: 2, feedback: \"Stop disables motion and preserves the actual pose instead of introducing an unexpected movement.\" },\n explain: { question: \"Why track enabled state separately from target angle?\", choices: [\"A valid pose is not itself permission to move\", \"It removes the need for angle bounds\", \"It changes the device into a real robot\"], correctChoice: 0, feedback: \"The project must satisfy both the movement permission and the range rule before applying a pose.\" },\n },\n },\n {\n title: \"Move a little at a time\", concepts: [\"Rate limits\", \"Floating arithmetic\", \"Arrival clamping\"],\n goals: [\"Approach a target at no more than 45 degrees per simulated second.\", \"Avoid overshoot and accumulated movement after a long stopped interval.\"],\n extension: \"Compare approach speeds 20 and 45 using the same target and observations. Explain how speed affects travel time while the final pose remains unchanged.\",\n activities: {\n learn: [\"Smooth motion changes angle by a bounded amount each observation. Compute dt=(now-lastTime)/1000.0, cap dt at 0.1 and use step=45×dt. Move toward the target by at most that step, clamping at arrival. Store angle and lastTime globally.\", \"The decimal 1000.0 matters: integer division could make short elapsed intervals become zero.\"],\n predict: [\"At 45 degrees per second and dt=0.02, predict the maximum change. If the remaining gap is only 0.3 degrees, decide whether to apply the whole normal step. Consider a long stopped interval before resuming.\", \"The ordinary step is 0.9 degrees, but a closer target needs only its remaining gap. Refresh time while stopped to prevent a large resume step.\"],\n build: [\"Write approach(current,target,step) as a double helper using min below the target and max above it. Update lastTime on every observation, including stop. While enabled, update the global angle through approach and emit that bounded value.\", \"Calculate elapsed time before replacing lastTime; replacing it first would make every dt zero.\"],\n run: [\"Step from 90 toward 120, then toward 60. Inspect consecutive angle differences and the final short arrival step. Stop for several observations, resume and confirm there is no sudden catch-up jump.\", \"Use the numeric trace to inspect smoothness even when reduced motion keeps the preview still.\"],\n assess: [\"Check both directions, exact arrival, small and large elapsed intervals, int-versus-double division and stop/resume timing. Requested angle changes must obey the 45-degree rate and remain within bounds.\", \"A slow-looking animation cannot prove correct rate limiting; the checks compare successive commanded values and simulated time.\"],\n inspect: [\"If nothing moves, inspect integer division and timestamp order. If it overshoots, inspect arrival clamping. If resuming jumps, inspect whether stopped observations still refresh lastTime.\", \"Separate current angle, target, elapsed seconds and allowed step while debugging the calculation.\"],\n fix: [\"Repair the calculation and replay the short-gap, reverse-direction and stopped-interval cases. Recheck enabled state and angle limits from the first mission so smoothing cannot bypass them.\", \"A new target does not permit a larger instantaneous step; the same approach rule applies in either direction.\"],\n explain: [\"Choose why the final step must be clamped to the target even when the rate is correct. Explain why simulated seconds and floating arithmetic belong together in this control loop.\", \"A rate describes how far movement may progress, not a requirement to overshoot a nearby destination.\"],\n reward: [\"Save Gentle movement. Your creature now reaches poses smoothly and resumes predictably. Next you will organise several target poses into a reusable timed sequence.\", \"Keep the 0.3-degree arrival case because it exposes a subtle overshoot error.\"],\n },\n questions: {\n learn: { question: \"Why divide elapsed milliseconds by 1000.0 rather than integer 1000?\", choices: [\"To make every interval ten seconds\", \"To ignore elapsed time\", \"To retain fractional seconds in short updates\"], correctChoice: 2, feedback: \"Floating division preserves small intervals such as 0.02 seconds instead of truncating them to zero.\" },\n predict: { question: \"At 45 degrees per second, what is the maximum change in 0.02 seconds?\", choices: [\"0.9 degrees\", \"45 degrees\", \"900 degrees\"], correctChoice: 0, feedback: \"The rate multiplied by elapsed seconds is 45 × 0.02 = 0.9 degrees.\" },\n explain: { question: \"Why refresh lastTime even during a stopped observation?\", choices: [\"To secretly move while stopped\", \"To prevent old stopped time becoming a large resume movement\", \"To erase the target\"], correctChoice: 1, feedback: \"The timestamp tracks the latest observation, so resuming does not treat the whole stopped period as one movement step.\" },\n },\n },\n {\n title: \"A sequence of poses\", concepts: [\"Parameters\", \"Timed phases\", \"Separation of concerns\"],\n goals: [\"Map three timed phases to target poses through one reusable helper.\", \"Keep target selection separate from the smooth movement and stop rules.\"],\n extension: \"Design a second sequence by changing only its target mapping. Keep the movement rate and phase interval unchanged so the comparison has one clear cause.\",\n activities: {\n learn: [\"A sequence selects targets; the approach helper moves toward them. Define poseForPhase with 60, 120 and 90 degrees for phases zero, one and two. Advance the phase every 2000 ms using modulo three. Each target still passes through the same smooth movement rule.\", \"Do not send the new target directly on a phase change, or the sequence will bypass smoothing exactly when it matters.\"],\n predict: [\"Starting at phase two, predict the next phase and target. Then compare changing a target to 120 with instantly commanding angle 120 while the current pose is 60.\", \"The target can change immediately while the actual angle approaches it over several observations.\"],\n build: [\"Add a phase variable, phase timestamp and poseForPhase helper. Update the phase only when the two-second interval elapses. During stop hold the phase and refresh its clock, then feed the current target to approach while active.\", \"Keep phase time distinct from lastTime used for movement steps; the two clocks represent different intervals.\"],\n run: [\"Step through two full sequences, pausing at a phase boundary. Watch target and current angle separately. Stop during the middle phase and resume to confirm the sequence does not skip ahead through the stopped time.\", \"A trace with phase, target and angle explains the sequence even without watching an animated joint.\"],\n assess: [\"Check all target mappings, wraparound, phase interval, held phase during stop and bounded movement on target changes. An unexpected phase should return the neutral 90-degree target.\", \"The helper must use its parameter so it can be checked independently of the live global phase.\"],\n inspect: [\"If target changes move instantly, inspect where approach is bypassed. If phases skip after stop, inspect the phase timestamp. If every phase uses one pose, inspect the helper's parameter comparisons.\", \"Test target selection separately from movement to find which part of the sequence is wrong.\"],\n fix: [\"Repair phase selection or timing and replay a full cycle plus a stop at a boundary. Preserve the movement-rate and enabled-state checks from earlier missions.\", \"Changing a sequence should not require rewriting the safe movement calculation.\"],\n explain: [\"Choose why target selection and movement belong in separate helpers. Explain how the same approach rule can support another sequence without repeating its safety logic.\", \"Separate responsibilities let one function decide where to go and another decide how far it may move now.\"],\n reward: [\"Save Living sequence. Your creature can perform a repeated set of smooth poses. Next you will give different target choices meaningful mood names and symbols.\", \"Keep the neutral fallback case when adding any new pose mappings.\"],\n },\n questions: {\n learn: { question: \"What should a phase change alter immediately?\", choices: [\"The selected target, while movement still approaches it\", \"Every safety limit\", \"The actual angle regardless of distance\"], correctChoice: 0, feedback: \"Selecting another target does not bypass the bounded approach used to move the joint.\" },\n predict: { question: \"Which phase and target follow phase two in the documented sequence?\", choices: [\"Phase three at 180\", \"Phase zero at 60\", \"Phase two forever\"], correctChoice: 1, feedback: \"Modulo three wraps the next phase back to zero, whose target is 60 degrees.\" },\n explain: { question: \"Why keep phase timing separate from the movement-step timestamp?\", choices: [\"To prevent all timing\", \"To make stop delay longer\", \"They measure different intervals and responsibilities\"], correctChoice: 2, feedback: \"One clock schedules target changes, while the other limits movement during each individual observation.\" },\n },\n },\n {\n title: \"Give the creature a mood\", concepts: [\"Named modes\", \"Input identity\", \"Fallbacks\"],\n goals: [\"Map calm, curious and happy requests to clear mood labels and target poses.\", \"Handle each new request once and use a safe fallback for unknown mood text.\"],\n extension: \"Propose another mood with a text label, symbol and bounded target. Explain how it would fit the existing mapping and which checks would need extending.\",\n activities: {\n learn: [\"A mood names a mode of behaviour. Map calm to a 90-degree target, curious to 120 and happy to 60, and emit the matching mood label. A moodRequestId identifies a new selection; repeated observations of the same request are not new instructions. Unknown mood text falls back to calm.\", \"The mode changes the target choice, not the angle bounds, movement rate or stop priority.\"],\n predict: [\"A curious request with id four arrives twice. Predict how many selection events it represents. Then an unknown mood arrives with id five; choose the target and label that should follow.\", \"Identity distinguishes a repeated observation from a new request, while validation decides whether the requested value is supported.\"],\n build: [\"Store mood and lastRequestId globally. On a new request id, validate requestedMood and select calm, curious or happy once. Add a helper that returns the mood target and pass that target through approach. Keep the sequence helper available as a separate exercise.\", \"Do not replace the current mood on every repeated observation, because a later touch event will also be able to change it.\"],\n run: [\"Select each mood with keyboard and onscreen controls. Inspect its label, symbol, target and actual approach. Repeat a request id and send an unknown value to compare identity handling with fallback handling.\", \"Meaning should remain clear from words and symbols even when the joint is paused or disabled.\"],\n assess: [\"Check all three mappings, repeated ids, a new invalid request and smooth movement toward a changed target. Tests require the unknown request to use calm without losing the safe control state.\", \"A new id is not proof that its text is valid. Apply both checks.\"],\n inspect: [\"If a repeated request keeps undoing another change, inspect lastRequestId. If a mood changes safety bounds, separate the mapping from control limits. If unknown text causes an arbitrary pose, inspect the fallback branch.\", \"Trace request id, requested text and accepted mood as three distinct values.\"],\n fix: [\"Repair request handling or mapping and repeat valid, duplicate and unknown selections. Recheck movement rate during a large target change and stop while a request arrives.\", \"A safe fallback should still leave the creature usable and explain which supported mood was selected.\"],\n explain: [\"Choose why a named mood can change expression without changing safety rules. Explain why repeated sensor records need identity when several kinds of interaction can change the same state.\", \"The interface describes intent; the control loop still enforces what motion is permitted.\"],\n reward: [\"Save Expressive creature. Your joint now has understandable modes driven by explicit requests. Next it will react once to touch and stop when a proximity observation makes movement unsafe.\", \"Keep a repeated request as a regression case when adding another input source.\"],\n },\n questions: {\n learn: { question: \"What should remain unchanged when the creature's mood changes?\", choices: [\"Only its text label\", \"Angle, movement-rate and stop protections\", \"The previous request id forever\"], correctChoice: 1, feedback: \"Mood chooses an expression target; the shared control limits and stop priority remain in force.\" },\n predict: { question: \"A new request contains an unknown mood; which documented fallback is used?\", choices: [\"An angle outside the range\", \"A random mood each frame\", \"Calm with a 90-degree target\"], correctChoice: 2, feedback: \"Unknown text has a predictable supported fallback, keeping both presentation and movement understandable.\" },\n explain: { question: \"Why remember the last mood request id?\", choices: [\"To process one request once instead of replaying the same observation\", \"To remove touch support\", \"To bypass text validation\"], correctChoice: 0, feedback: \"Identity prevents repeated observations from continually reapplying an old selection after other interactions.\" },\n },\n },\n {\n title: \"A gentle response to touch\", concepts: [\"Input edges\", \"Safety priority\", \"Fresh observations\"],\n goals: [\"Cycle moods once for each new touch while handling held input predictably.\", \"Disable movement for unsafe proximity and preserve input/time history through stop.\"],\n extension: \"Build a timeline of touch, hold, release and a nearby obstacle. Explain which observations change mood and which require holding the joint still.\",\n activities: {\n learn: [\"A new touch is touched&&!wasTouched, so a held sensor does not cycle moods repeatedly. Read distance fresh: values below 10 cm, below zero or above 400 disable the joint. Update touch history and timestamps even when movement is disabled, then return before sending angles.\", \"A sensor's reading is an observation, not a permanent promise that the space will remain clear.\"],\n predict: [\"Predict mood changes for false, true, true, false, true touch observations. Then hold touch while distance falls to five centimetres and later becomes clear: decide whether clearing the obstacle alone should create another touch event.\", \"Only a real false-to-true transition creates a new touch. Safety recovery must not invent an input edge.\"],\n build: [\"Add wasTouched and edge detection. Cycle calm to curious to happy to calm on a valid new touch. Give a new explicit mood request priority over a simultaneous edge. Apply stop and proximity guards before enabling or commanding the joint.\", \"Consume observation history while disabled, but do not move or apply a delayed old touch on resume.\"],\n run: [\"Use touch controls, hold through several observations and then release. Introduce near, invalid and clear distance readings while stepping. Inspect enabled state, actual angle, mood and previous-touch history together.\", \"The simulator offers supplied distance values; it does not request a physical sensor or camera connection.\"],\n assess: [\"Check touch edges, long holds, simultaneous request priority, stop, near and invalid distances, and safe recovery. Failed or mistyped sensor input must result in a stopped simulation rather than continued motion.\", \"A correct normal touch response does not establish that the priority safety branches work.\"],\n inspect: [\"If a hold changes mood repeatedly, inspect edge history. If a nearby obstacle is ignored, inspect fresh sensor reads and branch order. If resume jumps, inspect time updates during disabled observations.\", \"Look for the earliest observation where accepted input or enabled state differs from the documented rule.\"],\n fix: [\"Repair the input or safety branch and replay hold-through-stop and hold-through-near-obstacle cases. Confirm a later genuine new touch still works and every commanded angle remains bounded and smooth.\", \"Keep old input from replaying, while preserving useful future interaction after the space becomes clear.\"],\n explain: [\"Choose why safety observations take priority over expression. Explain how updating input history while disabled supports a predictable recovery without secretly moving the joint.\", \"Maintaining state and commanding movement are separate operations; the first can continue while the second is disabled.\"],\n reward: [\"Save Gentle reactions. Your creature now responds to deliberate touch and fresh safety observations. The final show integrates its expression, smooth motion and priority stop behaviour.\", \"Keep the simultaneous-request-and-touch case because it makes interaction priority explicit.\"],\n },\n questions: {\n learn: { question: \"What should happen when the supplied distance is five centimetres?\", choices: [\"Continue the show unchanged\", \"Speed up to move away blindly\", \"Disable the joint and hold its current pose\"], correctChoice: 2, feedback: \"The simulator's near-object rule stops motion before expression logic can issue another angle command.\" },\n predict: { question: \"Touch stays held while an obstacle appears and clears; does clearing create a new touch?\", choices: [\"No, the touch state never made a new rising edge\", \"Yes, every clear reading is a touch\", \"Yes, stop erases all input history\"], correctChoice: 0, feedback: \"Maintained touch history distinguishes a continuing hold from a new intentional press after release.\" },\n explain: { question: \"Which input wins when a new mood request and a touch edge arrive together?\", choices: [\"Both in an unspecified order\", \"The new explicit mood request\", \"Neither, and the joint must jump\"], correctChoice: 1, feedback: \"The documented priority applies the explicit selection once, avoiding two conflicting changes in one observation.\" },\n },\n },\n {\n title: \"The creature show\", concepts: [\"Integration\", \"Interaction priority\", \"Regression evidence\"],\n goals: [\"Present a complete responsive creature with named expression and smooth bounded movement.\", \"Preserve stop, proximity, request identity and touch-edge rules throughout the show and restart.\"],\n extension: \"Design a new expression sequence in a separate save. State its intended mood and replay the existing range, rate, stop and input-boundary checks before comparing it with the finished show.\",\n activities: {\n learn: [\"A finished creature combines understandable expression with a reliable controller. Keep one order: read fresh inputs, update time and touch history, apply safety guards, accept a new request or touch edge, choose a target and approach it. The sequence exercise can reuse the same movement helper.\", \"The same safety controller should support both a pose sequence and an interactive mood demonstration.\"],\n predict: [\"Predict a show observation with a new happy request, a touch edge and stop true. Then release stop without releasing touch and consider a later genuine new request. Identify which state may update and which movement is forbidden.\", \"Stop prevents movement regardless of expression input. Updated history prevents an old held touch from replaying on recovery.\"],\n build: [\"Combine the verified helpers into the interactive show, retaining a separately named sequence helper for replay. Keep control state explicit and use one bounded movement path. Restart with a fresh session at 90 degrees, disabled, calm and with fresh timing history.\", \"Do not let a new feature issue angle commands through another path that bypasses the shared checks.\"],\n run: [\"Demonstrate each mood using keyboard and touch controls, then run the pose sequence exercise. Pause, stop, introduce a near reading, recover and restart. Compare status text, symbols, target and actual angle in reduced-motion mode.\", \"A complete demonstration should remain understandable without watching every movement.\"],\n assess: [\"Assess the saved final project across target changes, short and delayed observations, duplicate requests, held touch, simultaneous inputs, proximity and stop. Check the earlier pose helper as well as the interactive controller.\", \"The capstone verifies the integrated rules, not merely whether the creature reaches one attractive final pose.\"],\n inspect: [\"Locate the first incorrect command in a failing trace and identify which priority or bound allowed it. Separate target-selection errors from motion-rate errors and input-history errors before choosing a repair.\", \"A correct final angle can hide an unsafe intermediate jump; inspect the full commanded sequence.\"],\n fix: [\"Repair the controller and rerun the focused failure plus earlier bounds, arrival, sequence and touch cases. Save and assess the exact new source before finishing, keeping a stable named version for later experiments.\", \"Do not hide an overspeed command by slowing only the animation. Repair the values the programme emits.\"],\n explain: [\"Choose what makes the creature show predictable and describe how one extension could affect existing rules. Explain the distinction between this supplied-input simulator and an independently approved physical build.\", \"The project demonstrates programming evidence; it does not grant permission to connect or operate equipment.\"],\n reward: [\"Save Creature show and complete the final assessment. You have built a responsive simulated character with reusable functions, smooth motion and explicit input priorities. Replay missions or experiment in another named save while retaining earned completion.\", \"Keep the tested version before extending the show. Existing guardian and hardware protections remain separate from completing the simulator.\"],\n },\n questions: {\n learn: { question: \"Where should every angle command pass before reaching the simulated joint?\", choices: [\"Through the shared safety and bounded movement rules\", \"Through whichever mood branch runs last\", \"Directly from any unvalidated sensor string\"], correctChoice: 0, feedback: \"A single shared control path keeps new expressions from bypassing range, rate and stop requirements.\" },\n predict: { question: \"A happy request and touch arrive while stop is true; may the joint move?\", choices: [\"Yes, because two inputs arrived\", \"No, stop retains priority over expression\", \"Only beyond the normal angle limits\"], correctChoice: 1, feedback: \"Expression inputs do not override the movement guard. The stopped controller holds its actual pose.\" },\n explain: { question: \"What does passing the creature simulator's final checks establish?\", choices: [\"Automatic approval for any real servo build\", \"That future source changes need no checks\", \"Evidence that the documented simulated controller behaves correctly\"], correctChoice: 2, feedback: \"The assessment covers the supplied simulator scenarios; physical equipment and future changes require their own appropriate checks.\" },\n },\n },\n]);\n"],"mappings":";;;;;;AAEO,IAAM,EAAE,QAAQ,SAAS,IAAI,aAAa;AAAA,EAC/C,MAAM;AAAA,EAAkB,OAAO;AAAA,EAAkB,UAAU;AAAA,EAC3D,SAAS;AAAA,EACT,cAAc,CAAC,EAAE,MAAM,aAAa,UAAU,OAAO,mBAAmB,KAAM,CAAC;AAAA,EAC/E,gBAAgB,EAAE,OAAO,CAAC,EAAE,MAAM,aAAa,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAavD,CAAC,EAAE;AAAA,EACH,WAAW;AAAA,IACT,EAAE,MAAM,mBAAmB,WAAW,iCAAiC,aAAa,uNAAuN,SAAS,8DAA8D;AAAA,IAClX,EAAE,MAAM,iBAAiB,WAAW,iCAAiC,aAAa,2OAA2O,SAAS,qDAAqD;AAAA,IAC3X,EAAE,MAAM,UAAU,WAAW,gBAAgB,aAAa,2NAA2N,SAAS,6EAA6E;AAAA,IAC3W,EAAE,MAAM,YAAY,WAAW,+DAA+D,aAAa,gMAAgM,SAAS,gGAAgG;AAAA,IACpZ,EAAE,MAAM,mBAAmB,WAAW,gCAAgC,aAAa,2LAA2L,SAAS,8BAA8B;AAAA,IACrT,EAAE,MAAM,iBAAiB,WAAW,+DAA+D,aAAa,wOAAwO,SAAS,gHAAgH;AAAA,IACjd,EAAE,MAAM,uBAAuB,WAAW,oDAAoD,aAAa,uNAAuN,SAAS,kGAAkG;AAAA,IAC7a,EAAE,MAAM,iBAAiB,WAAW,kCAAkC,aAAa,kPAAkP,SAAS,2BAA2B;AAAA,EAC3W;AACF,GAAG;AAAA,EACD;AAAA,IACE,OAAO;AAAA,IAA4B,UAAU,CAAC,UAAU,UAAU,eAAe;AAAA,IACjF,OAAO,CAAC,6EAAwE,qEAAqE;AAAA,IACrJ,WAAW;AAAA,IACX,YAAY;AAAA,MACV,OAAO,CAAC,uQAAuQ,yGAAyG;AAAA,MACxX,SAAS,CAAC,4KAA4K,6GAA6G;AAAA,MACnS,OAAO,CAAC,8MAA8M,+FAA+F;AAAA,MACrT,KAAK,CAAC,mMAAmM,iFAAiF;AAAA,MAC1R,QAAQ,CAAC,uMAAuM,6HAA6H;AAAA,MAC7U,SAAS,CAAC,sPAAsP,gHAAgH;AAAA,MAChX,KAAK,CAAC,0MAA0M,mFAAmF;AAAA,MACnS,SAAS,CAAC,6LAA6L,qGAAqG;AAAA,MAC5S,QAAQ,CAAC,yLAAyL,kEAAkE;AAAA,IACtQ;AAAA,IACA,WAAW;AAAA,MACT,OAAO,EAAE,UAAU,sDAAsD,SAAS,CAAC,oBAAoB,0BAA0B,uBAAuB,GAAG,eAAe,GAAG,UAAU,8FAA8F;AAAA,MACrR,SAAS,EAAE,UAAU,0EAA0E,SAAS,CAAC,4BAA4B,iCAAiC,oCAAoC,GAAG,eAAe,GAAG,UAAU,oGAAoG;AAAA,MAC7U,SAAS,EAAE,UAAU,yDAAyD,SAAS,CAAC,iDAAiD,wCAAwC,yCAAyC,GAAG,eAAe,GAAG,UAAU,mGAAmG;AAAA,IAC9V;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IAA2B,UAAU,CAAC,eAAe,uBAAuB,kBAAkB;AAAA,IACrG,OAAO,CAAC,sEAAsE,yEAAyE;AAAA,IACvJ,WAAW;AAAA,IACX,YAAY;AAAA,MACV,OAAO,CAAC,iPAA8O,8FAA8F;AAAA,MACpV,SAAS,CAAC,gNAAgN,gJAAgJ;AAAA,MAC1W,OAAO,CAAC,kPAAkP,gGAAgG;AAAA,MAC1V,KAAK,CAAC,wMAAwM,+FAA+F;AAAA,MAC7S,QAAQ,CAAC,8MAA8M,iIAAiI;AAAA,MACxV,SAAS,CAAC,+LAA+L,mGAAmG;AAAA,MAC5S,KAAK,CAAC,iMAAiM,+GAA+G;AAAA,MACtT,SAAS,CAAC,sLAAsL,sGAAsG;AAAA,MACtS,QAAQ,CAAC,uKAAuK,+EAA+E;AAAA,IACjQ;AAAA,IACA,WAAW;AAAA,MACT,OAAO,EAAE,UAAU,uEAAuE,SAAS,CAAC,sCAAsC,0BAA0B,+CAA+C,GAAG,eAAe,GAAG,UAAU,uGAAuG;AAAA,MACzV,SAAS,EAAE,UAAU,yEAAyE,SAAS,CAAC,eAAe,cAAc,aAAa,GAAG,eAAe,GAAG,UAAU,wEAAqE;AAAA,MACtP,SAAS,EAAE,UAAU,2DAA2D,SAAS,CAAC,kCAAkC,gEAAgE,qBAAqB,GAAG,eAAe,GAAG,UAAU,yHAAyH;AAAA,IAC3W;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IAAuB,UAAU,CAAC,cAAc,gBAAgB,wBAAwB;AAAA,IAC/F,OAAO,CAAC,uEAAuE,yEAAyE;AAAA,IACxJ,WAAW;AAAA,IACX,YAAY;AAAA,MACV,OAAO,CAAC,wQAAwQ,uHAAuH;AAAA,MACvY,SAAS,CAAC,qKAAqK,mGAAmG;AAAA,MAClR,OAAO,CAAC,uOAAuO,+GAA+G;AAAA,MAC9V,KAAK,CAAC,0NAA0N,qGAAqG;AAAA,MACrU,QAAQ,CAAC,yLAAyL,gGAAgG;AAAA,MAClS,SAAS,CAAC,2MAA2M,6FAA6F;AAAA,MAClT,KAAK,CAAC,kKAAkK,iFAAiF;AAAA,MACzP,SAAS,CAAC,4KAA4K,2GAA2G;AAAA,MACjS,QAAQ,CAAC,kKAAkK,mEAAmE;AAAA,IAChP;AAAA,IACA,WAAW;AAAA,MACT,OAAO,EAAE,UAAU,iDAAiD,SAAS,CAAC,2DAA2D,sBAAsB,yCAAyC,GAAG,eAAe,GAAG,UAAU,wFAAwF;AAAA,MAC/T,SAAS,EAAE,UAAU,uEAAuE,SAAS,CAAC,sBAAsB,oBAAoB,mBAAmB,GAAG,eAAe,GAAG,UAAU,8EAA8E;AAAA,MAChR,SAAS,EAAE,UAAU,oEAAoE,SAAS,CAAC,yBAAyB,6BAA6B,uDAAuD,GAAG,eAAe,GAAG,UAAU,0GAA0G;AAAA,IAC3V;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IAA4B,UAAU,CAAC,eAAe,kBAAkB,WAAW;AAAA,IAC1F,OAAO,CAAC,+EAA+E,6EAA6E;AAAA,IACpK,WAAW;AAAA,IACX,YAAY;AAAA,MACV,OAAO,CAAC,6RAA6R,2FAA2F;AAAA,MAChY,SAAS,CAAC,6LAA6L,sIAAsI;AAAA,MAC7U,OAAO,CAAC,0QAA0Q,4HAA4H;AAAA,MAC9Y,KAAK,CAAC,mNAAmN,+FAA+F;AAAA,MACxT,QAAQ,CAAC,mMAAmM,kEAAkE;AAAA,MAC9Q,SAAS,CAAC,gOAAgO,8EAA8E;AAAA,MACxT,KAAK,CAAC,+KAA+K,uGAAuG;AAAA,MAC5R,SAAS,CAAC,+LAA+L,2FAA2F;AAAA,MACpS,QAAQ,CAAC,gMAAgM,gFAAgF;AAAA,IAC3R;AAAA,IACA,WAAW;AAAA,MACT,OAAO,EAAE,UAAU,kEAAkE,SAAS,CAAC,uBAAuB,6CAA6C,iCAAiC,GAAG,eAAe,GAAG,UAAU,kGAAkG;AAAA,MACrU,SAAS,EAAE,UAAU,8EAA8E,SAAS,CAAC,8BAA8B,4BAA4B,8BAA8B,GAAG,eAAe,GAAG,UAAU,4GAA4G;AAAA,MAChV,SAAS,EAAE,UAAU,0CAA0C,SAAS,CAAC,yEAAyE,2BAA2B,2BAA2B,GAAG,eAAe,GAAG,UAAU,iHAAiH;AAAA,IAC1V;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IAA8B,UAAU,CAAC,eAAe,mBAAmB,oBAAoB;AAAA,IACtG,OAAO,CAAC,8EAA8E,qFAAqF;AAAA,IAC3K,WAAW;AAAA,IACX,YAAY;AAAA,MACV,OAAO,CAAC,qRAAqR,iGAAiG;AAAA,MAC9X,SAAS,CAAC,+OAA+O,0GAA0G;AAAA,MACnW,OAAO,CAAC,gPAAgP,qGAAqG;AAAA,MAC7V,KAAK,CAAC,8NAA8N,4GAA4G;AAAA,MAChV,QAAQ,CAAC,wNAAwN,4FAA4F;AAAA,MAC7T,SAAS,CAAC,8MAA8M,2GAA2G;AAAA,MACnU,KAAK,CAAC,4MAA4M,0GAA0G;AAAA,MAC5T,SAAS,CAAC,sLAAsL,yHAAyH;AAAA,MACzT,QAAQ,CAAC,6LAA6L,8FAA8F;AAAA,IACtS;AAAA,IACA,WAAW;AAAA,MACT,OAAO,EAAE,UAAU,sEAAsE,SAAS,CAAC,+BAA+B,iCAAiC,6CAA6C,GAAG,eAAe,GAAG,UAAU,yGAAyG;AAAA,MACxV,SAAS,EAAE,UAAU,4FAA4F,SAAS,CAAC,oDAAoD,uCAAuC,oCAAoC,GAAG,eAAe,GAAG,UAAU,uGAAuG;AAAA,MAChY,SAAS,EAAE,UAAU,8EAA8E,SAAS,CAAC,gCAAgC,iCAAiC,kCAAkC,GAAG,eAAe,GAAG,UAAU,oHAAoH;AAAA,IACrW;AAAA,EACF;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IAAqB,UAAU,CAAC,eAAe,wBAAwB,qBAAqB;AAAA,IACnG,OAAO,CAAC,6FAA6F,kGAAkG;AAAA,IACvM,WAAW;AAAA,IACX,YAAY;AAAA,MACV,OAAO,CAAC,4SAA4S,uGAAuG;AAAA,MAC3Z,SAAS,CAAC,yOAAyO,+HAA+H;AAAA,MAClX,OAAO,CAAC,6QAA6Q,qGAAqG;AAAA,MAC1X,KAAK,CAAC,2OAA2O,wFAAwF;AAAA,MACzU,QAAQ,CAAC,uOAAuO,gHAAgH;AAAA,MAChW,SAAS,CAAC,sNAAsN,kGAAkG;AAAA,MAClU,KAAK,CAAC,4NAA4N,wGAAwG;AAAA,MAC1U,SAAS,CAAC,2NAA2N,8GAA8G;AAAA,MACnV,QAAQ,CAAC,sQAAsQ,8IAA8I;AAAA,IAC/Z;AAAA,IACA,WAAW;AAAA,MACT,OAAO,EAAE,UAAU,8EAA8E,SAAS,CAAC,wDAAwD,2CAA2C,6CAA6C,GAAG,eAAe,GAAG,UAAU,uGAAuG;AAAA,MACjY,SAAS,EAAE,UAAU,4EAA4E,SAAS,CAAC,mCAAmC,6CAA6C,qCAAqC,GAAG,eAAe,GAAG,UAAU,sGAAsG;AAAA,MACrW,SAAS,EAAE,UAAU,sEAAsE,SAAS,CAAC,+CAA+C,6CAA6C,qEAAqE,GAAG,eAAe,GAAG,UAAU,sIAAsI;AAAA,IAC7a;AAAA,EACF;AACF,CAAC;","names":[]}