diff --git a/data/lessons.js b/data/lessons.js
index 8873738..9838526 100644
--- a/data/lessons.js
+++ b/data/lessons.js
@@ -13,7 +13,34 @@ export const lessons = [
You should see "Hello World" printed in the output area
`,
- doneCondition: (consoleText) => consoleText.includes("Hello World")
+ doneCondition: (() => {
+ const progress = {
+ stringDone: false
+ };
+
+ return ({ code, consoleText, codeRanGood }) => {
+ if (codeRanGood && !progress.stringDone && consoleText.includes("Hello World")) {
+ progress.stringDone = true;
+ }
+
+ const missing = [];
+ if (!progress.stringDone) missing.push("Hello World");
+
+ let hint = "I still need you to print ";
+ if (missing.length === 0) {
+ hint = "";
+ } else if (missing.length === 1) {
+ hint += missing[0];
+ } else {
+ hint += missing.slice(0, -1).join(", ") + " and " + missing[missing.length - 1];
+ }
+
+ return {
+ done: progress.stringDone,
+ hint
+ };
+ };
+ })()
},
{
id: 'lesson2',
@@ -36,65 +63,60 @@ export const lessons = [
Click the "Run" button to execute your code
`,
- doneCondition: (consoleText => {
- // Persistent tracking object inside closure
+ doneCondition: (() => {
const progress = {
stringDone: false,
intDone: false,
floatDone: false,
boolDone: false,
- syntaxErrorDone: false,
+ // syntaxErrorDone: false, // optional
};
- //const syntaxErrorRegex = /SyntaxError/i;
- const stringRegex = /(["'])(?:(?=(\\?))\2.)*?\1/; // optional improvement based on context
+ const stringRegex = /(["'])(?:(?=(\\?))\2.)*?\1/;
const intRegex = /(? {
+ return ({ code, consoleText, codeRanGood }) => {
+ if (!codeRanGood) {
+ return {
+ done: false,
+ hint: "Your code had an error — try fixing it and run again."
+ };
+ }
-
- // if (!progress.syntaxErrorDone && syntaxErrorRegex.test(text)) {
- // progress.syntaxErrorDone = true;
- // }
- if (!progress.stringDone && stringRegex.test(text)) {
+ if (!progress.stringDone && stringRegex.test(consoleText)) {
progress.stringDone = true;
}
- if (!progress.floatDone && floatRegex.test(text)) {
+ if (!progress.floatDone && floatRegex.test(consoleText)) {
progress.floatDone = true;
}
- if (!progress.intDone && intRegex.test(text)) {
+ if (!progress.intDone && intRegex.test(consoleText)) {
progress.intDone = true;
}
- if (!progress.boolDone && boolRegex.test(text)) {
+ if (!progress.boolDone && boolRegex.test(consoleText)) {
progress.boolDone = true;
}
- let missing = [];
-
- //if (!progress.syntaxErrorDone) missing.push("syntax error");
- //if (!progress.stringDone) missing.push("string");
+ const missing = [];
if (!progress.floatDone) missing.push("float");
if (!progress.intDone) missing.push("int");
if (!progress.boolDone) missing.push("boolean");
- let hint = "I still need you to print a ";
+ let hint = "I still need you to print a ";
if (missing.length === 0) {
hint = "";
} else if (missing.length === 1) {
hint += missing[0];
} else {
- // Join all but last with comma, then add 'and' + last
hint += missing.slice(0, -1).join(", ") + " and " + missing[missing.length - 1];
}
-
const done = progress.intDone && progress.floatDone && progress.boolDone;
-
return { done, hint };
};
})()
+
},
{
id: 'lesson3',
@@ -111,7 +133,7 @@ export const lessons = [
Division: print(20 / 5)
`,
- doneCondition: (consoleText => {
+ doneCondition: (() => {
// Persistent tracking object inside closure
const progress = {
addDone: false,
@@ -123,22 +145,27 @@ export const lessons = [
- return (text) => {
-
+ return ({ code, consoleText, codeRanGood }) => {
+ if (!codeRanGood) {
+ return {
+ done: false,
+ hint: ""
+ };
+ }
// if (!progress.syntaxErrorDone && syntaxErrorRegex.test(text)) {
// progress.syntaxErrorDone = true;
// }
- if (!progress.addDone && text.includes("+")) {
+ if (!progress.addDone && code.includes("+")) {
progress.addDone = true;
}
- if (!progress.subDone && text.includes("-")) {
+ if (!progress.subDone && code.includes("-")) {
progress.subDone = true;
}
- if (!progress.mulDone && text.includes("*")) {
+ if (!progress.mulDone && code.includes("*")) {
progress.mulDone = true;
}
- if (!progress.divDone && text.includes("/")) {
+ if (!progress.divDone && code.includes("/")) {
progress.divDone = true;
}
@@ -198,55 +225,418 @@ export const lessons = [
doneCondition: (text) => text.includes("8"),
}
],
- doneCondition: (code => {
- const progress = {
- varCreated: false,
- varPrinted: false,
- varName: null,
- };
+ doneCondition: (() => {
+ const progress = {
+ varCreated: false,
+ varPrinted: false,
+ varName: null,
+ };
- return (text) => {
- // Extract variable name from current text each time
- const assignMatch = text.match(/^\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*=/m);
- if (assignMatch) {
- progress.varName = assignMatch[1];
- progress.varCreated = true;
- } else {
- // No variable assignment found this run
- progress.varCreated = false;
- progress.varName = null;
- progress.varPrinted = false; // reset printed too because no var
- }
+ return ({ code, consoleText, codeRanGood }) => {
+ if (!codeRanGood) {
+ return {
+ done: false,
+ hint: ""
+ };
+ }
+ const assignMatch = code.match(/^\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*=/m);
+ if (assignMatch) {
+ progress.varName = assignMatch[1];
+ progress.varCreated = true;
+ } else {
+ progress.varCreated = false;
+ progress.varName = null;
+ progress.varPrinted = false;
+ }
- // Check if variable is printed in this run (only if varName exists)
- if (progress.varCreated && progress.varName) {
- const printRegex = new RegExp(`print\\s*\\(\\s*${progress.varName}\\s*\\)`);
- if (printRegex.test(text)) {
- progress.varPrinted = true;
- } else {
- progress.varPrinted = false; // reset if print no longer found
+ if (progress.varCreated && progress.varName) {
+ const printRegex = new RegExp(`print\\s*\\(\\s*${progress.varName}\\s*\\)`);
+ if (printRegex.test(code)) {
+ progress.varPrinted = true;
+ } else {
+ progress.varPrinted = false;
+ }
+ }
+
+ console.log('varCreated:', progress.varCreated, 'varPrinted:', progress.varPrinted);
+
+ let missing = [];
+ if (!progress.varCreated) missing.push("create a variable");
+ if (!progress.varPrinted) missing.push("print the variable");
+
+ let hint = "I still need you to ";
+ if (missing.length === 0) {
+ hint = "";
+ } else if (missing.length === 1) {
+ hint += missing[0];
+ } else {
+ hint += missing.slice(0, -1).join(", ") + " and " + missing[missing.length - 1];
+ }
+
+ const done = progress.varCreated && progress.varPrinted;
+ return { done, hint };
+ };
+ })()
+ },
+ {
+ id: 'lesson5',
+ title: '5. More on Variables',
+ difficulty: 'easy',
+ content: `
+ A variable will act like any other object of its data type.
+ For example, if we have a variable called bob with the value 32, we can do math with it:
+ print(bob + 10) will print 42.
+
+ We can also change the value of a variable:
+
+bob = 32
+print(bob)
+bob = bob + 10
+print(bob)
+
+ In this example, the first time you print bob it will give his initial value of 32, but the second time we have added 10 to bob.
+ Give it a try.
+ `,
+ steps: [
+ {
+ content: `First, try printing an addition: print(2 + 3)
`,
+ doneCondition: (text) => text.includes("5"),
+ },
+ {
+ content: `Nice! Now try subtraction: print(5 - 2)
`,
+ doneCondition: (text) => text.includes("3"),
+ },
+ {
+ content: `Now try multiplication: print(4 * 2)
`,
+ doneCondition: (text) => text.includes("8"),
}
- }
+ ],
+ doneCondition: (() => {
+ const progress = {
+ varCreated: false,
+ varPrinted: false,
+ varArithmeticDone: false,
+ varPrintedTwice: false,
+ };
- // Build hint
- let missing = [];
- if (!progress.varCreated) missing.push("create a variable");
- if (progress.varCreated && !progress.varPrinted) missing.push("print the variable");
+ return ({ code, consoleText, codeRanGood }) => {
+ if (!codeRanGood) {
+ return {
+ done: false,
+ hint: ""
+ };
+ }
+ const assignRegex = /\b(\w+)\s*=\s*[\d'"]/; // variable assignment
+ const printRegex1 = /print\(\s*\1\s*\)/; // first print of the variable
+ const mathRegex = /\1\s*=\s*\1\s*[\+\-\*/]\s*[\d'"]/; // arithmetic using itself
+ const printRegex2 = /print\(\s*\1\s*\)/; // second print of the variable
- let hint = "I still need you to ";
- if (missing.length === 0) {
- hint = "";
- } else if (missing.length === 1) {
- hint += missing[0];
- } else {
- hint += missing.slice(0, -1).join(", ") + " and " + missing[missing.length - 1];
- }
+ const match = code.match(assignRegex);
+ if (!match) return false;
- const done = progress.varCreated && progress.varPrinted;
- return { done, hint };
- };
-})()
+ const varName = match[1];
+ const dynamicPrint1 = new RegExp(`print\\(\\s*${varName}\\s*\\)`);
+ const dynamicMath = new RegExp(`${varName}\\s*=\\s*${varName}\\s*[+\\-*/]\\s*[\\d'"]`);
+ const dynamicPrint2 = new RegExp(`print\\(\\s*${varName}\\s*\\)`, 'g');
+ progress.varCreated = match;
+ progress.dynamicPrint1 = dynamicPrint1.test(code);
+ progress.varArithmeticDone = dynamicMath.test(code);
+ progress.varPrintedTwice = (code.match(dynamicPrint2) || []).length >= 2
+
+ let missing = [];
+ if (!progress.varCreated) missing.push("create a variable");
+ if (!progress.dynamicPrint1) missing.push("print the variable");
+ if (!progress.varArithmeticDone) missing.push("alter the variable");
+ if (!progress.varPrintedTwice) missing.push("print the variable a second time");
+
+ let hint = "I still need you to ";
+ if (missing.length === 0) {
+ hint = "";
+ } else if (missing.length === 1) {
+ hint += missing[0];
+ } else {
+ hint += missing.slice(0, -1).join(", ") + " and " + missing[missing.length - 1];
+ }
+
+ const done = progress.varCreated && progress.dynamicPrint1 && progress.varArithmeticDone && progress.varPrintedTwice;
+ return { done, hint };
+ };
+ })()
+ },
+ {
+ id: 'lesson6',
+ title: '6. Conditionals',
+ difficulty: 'easy',
+ content: `
+ Sometimes we want don't want part of our code to run, or we want it to run differently in different situations. That's when we use conditionals.
+
+bob = 5
+if bob > 10:
+ print("Bob is greater than 10")
+
+ In this example, the print function will only run if bob is 11 or higher.
+
+ One thing to note here is the formatting. Note that after the if bob > 10: there is a colon (:)
+
This tells Python that the next line is part of a new block of code.
+ In Python, we use indentation to define blocks of code, so the next line must be indented.
+ After the else: we also have a colon, and the next line is indented again.
+ Try it for yourself:
+
+ - Initialize a variable with a value
+ - Use an
if statement to check if the variable is greater or less than a value
+ - Print a message based on the condition
+
+ To test if two values are equal, you can use the == operator.
+ eg.
+num = 10
+if num == 10:
+ print("num is equal to 10")
+
+ `,
+
+ doneCondition: (() => {
+ const progress = {
+ varCreated: false,
+ ifStatement: false,
+ printedSomething: false,
+ };
+
+ return ({ code, consoleText, codeRanGood }) => {
+ if (!codeRanGood) {
+ return {
+ done: false,
+ hint: ""
+ };
+ }
+
+ // Check for variable assignment
+ const assignRegex = /\b(\w+)\s*=\s*[\d'"]/;
+ progress.varCreated = assignRegex.test(code);
+
+ // Check for if statement
+ progress.ifStatement = /(^|\n)\s*if\s+.*:/.test(code);
+
+ // Check for print() anywhere
+ progress.printedSomething = /print\s*\(.*\)/.test(code);
+
+ // Build hint
+ const missing = [];
+ if (!progress.varCreated) missing.push("create a variable");
+ if (!progress.ifStatement) missing.push("use an if statement");
+ if (!progress.printedSomething) missing.push("print something");
+
+ let hint = "";
+ if (missing.length > 0) {
+ hint = "I still need you to " + (missing.length === 1
+ ? missing[0]
+ : missing.slice(0, -1).join(", ") + " and " + missing[missing.length - 1]);
+ }
+
+ const done = progress.varCreated && progress.ifStatement && progress.printedSomething;
+ return { done, hint };
+ };
+ })()
},
+ {
+ id: 'lesson7',
+ title: '7. More Conditionals',
+ difficulty: 'easy',
+ content: `
+ Sometimes we'll want to run one thing OR another, rather than just running something or not. To do this we chain our if statements together with elif and else.
+
+bob = 10
+if bob == 10:
+ print("bob is equal to 10")
+elif bob < 10:
+ print("bob is less than 10")
+else:
+ print("bob is greater than 10")
+
+ In this example, only one of the print statements can ever run, elif is short for "else if", and is a second if statement which is only tested it the if above it resolves to False.
+ The else statement is run if all previous conditions are False.
+ You can chain as many elif statements as you like, but only one else at the end.
+ Try it for yourself:
+ `,
+
+ doneCondition: (() => {
+ const progress = {
+ varCreated: false,
+ ifStatement: false,
+ elifStatement: false,
+ elseStatement: false,
+ threeDistinctPrints: false,
+ };
+
+ return ({ code, consoleText, codeRanGood }) => {
+ if (!codeRanGood) {
+ return { done: false, hint: "" };
+ }
+
+ // 1. Variable assignment
+ const assignRegex = /\b(\w+)\s*=\s*[\d'"]/;
+ progress.varCreated = assignRegex.test(code);
+
+ // 2. Line-by-line block tracking
+ const lines = code.split('\n');
+ let currentBlock = null;
+ const printContents = {
+ if: null,
+ elif: null,
+ else: null,
+ };
+
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i].trim();
+
+ if (/^if\s+.*:/.test(line)) {
+ progress.ifStatement = true;
+ currentBlock = "if";
+ continue;
+ }
+
+ if (/^elif\s+.*:/.test(line)) {
+ progress.elifStatement = true;
+ currentBlock = "elif";
+ continue;
+ }
+
+ if (/^else\s*:/.test(line)) {
+ progress.elseStatement = true;
+ currentBlock = "else";
+ continue;
+ }
+
+ const printMatch = line.match(/print\s*\((.*?)\)/);
+ if (printMatch && currentBlock && !printContents[currentBlock]) {
+ const cleaned = printMatch[1].replace(/\s+/g, '').toLowerCase();
+ printContents[currentBlock] = cleaned;
+ }
+ }
+
+ const printedValues = Object.values(printContents).filter(Boolean);
+ const uniqueValues = new Set(printedValues);
+ progress.threeDistinctPrints = uniqueValues.size === 3;
+
+ // Hint generation
+ const missing = [];
+ if (!progress.varCreated) missing.push("create a variable");
+ if (!progress.ifStatement) missing.push("use an if statement");
+ if (!progress.elifStatement) missing.push("use an elif statement");
+ if (!progress.elseStatement) missing.push("use an else statement");
+ if (!progress.threeDistinctPrints) missing.push("print different things in the if, elif, and else blocks");
+
+ const hint = missing.length > 0
+ ? "I still need you to " + (missing.length === 1
+ ? missing[0]
+ : missing.slice(0, -1).join(", ") + " and " + missing[missing.length - 1])
+ : "";
+
+ const done = progress.varCreated && progress.ifStatement && progress.elifStatement &&
+ progress.elseStatement && progress.threeDistinctPrints;
+
+ return { done, hint };
+ };
+ })()
+ },
+ {
+ id: 'lesson8',
+ title: '8. Loops',
+ difficulty: 'easy',
+ content: `
+ Most of the time we'll want our code to run multiple times, or even endlessly, in that case we need loops.
+ Python has two main types of loops: for loops and while loops.
+ The while loop will continue to run as long as a condition is True.
+
+count = 0
+while count < 5:
+ print("Count is:", count)
+ count = count + 1
+print("Done!")
+
+ You have to be careful with while loops, if the condition never becomes False, the loop will run forever!
+
+ `,
+
+ doneCondition: (() => {
+ const progress = {
+ varCreated: false,
+ ifStatement: false,
+ elifStatement: false,
+ elseStatement: false,
+ threeDistinctPrints: false,
+ };
+
+ return ({ code, consoleText, codeRanGood }) => {
+ if (!codeRanGood) {
+ return { done: false, hint: "" };
+ }
+
+ // 1. Variable assignment
+ const assignRegex = /\b(\w+)\s*=\s*[\d'"]/;
+ progress.varCreated = assignRegex.test(code);
+
+ // 2. Line-by-line block tracking
+ const lines = code.split('\n');
+ let currentBlock = null;
+ const printContents = {
+ if: null,
+ elif: null,
+ else: null,
+ };
+
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i].trim();
+
+ if (/^if\s+.*:/.test(line)) {
+ progress.ifStatement = true;
+ currentBlock = "if";
+ continue;
+ }
+
+ if (/^elif\s+.*:/.test(line)) {
+ progress.elifStatement = true;
+ currentBlock = "elif";
+ continue;
+ }
+
+ if (/^else\s*:/.test(line)) {
+ progress.elseStatement = true;
+ currentBlock = "else";
+ continue;
+ }
+
+ const printMatch = line.match(/print\s*\((.*?)\)/);
+ if (printMatch && currentBlock && !printContents[currentBlock]) {
+ const cleaned = printMatch[1].replace(/\s+/g, '').toLowerCase();
+ printContents[currentBlock] = cleaned;
+ }
+ }
+
+ const printedValues = Object.values(printContents).filter(Boolean);
+ const uniqueValues = new Set(printedValues);
+ progress.threeDistinctPrints = uniqueValues.size === 3;
+
+ // Hint generation
+ const missing = [];
+ if (!progress.varCreated) missing.push("create a variable");
+ if (!progress.ifStatement) missing.push("use an if statement");
+ if (!progress.elifStatement) missing.push("use an elif statement");
+ if (!progress.elseStatement) missing.push("use an else statement");
+ if (!progress.threeDistinctPrints) missing.push("print different things in the if, elif, and else blocks");
+
+ const hint = missing.length > 0
+ ? "I still need you to " + (missing.length === 1
+ ? missing[0]
+ : missing.slice(0, -1).join(", ") + " and " + missing[missing.length - 1])
+ : "";
+
+ const done = progress.varCreated && progress.ifStatement && progress.elifStatement &&
+ progress.elseStatement && progress.threeDistinctPrints;
+
+ return { done, hint };
+ };
+ })()
+ },
];
diff --git a/data/lessons.json b/data/lessons.json
deleted file mode 100644
index 876afa6..0000000
--- a/data/lessons.json
+++ /dev/null
@@ -1,10 +0,0 @@
-[
- {
- "title": "Lesson 1",
- "content": "Welcome to Python. We are going to learn how to use python to control robots, but we need some basics first.Let's start with the basics of Python programming. Python is a versatile language that is easy to learn and widely used in robotics.
"
- },
- {
- "title": "Lesson 2",
- "content": "Now let's learn about interrupts..."
- }
-]
\ No newline at end of file
diff --git a/game.js b/game.js
index 7368e27..2046943 100644
--- a/game.js
+++ b/game.js
@@ -2,7 +2,9 @@ import { Robot } from "./robot.js";
import { GameWorld } from "./gameworld.js";
import { lessons } from './data/lessons.js';
-
+let mostRecentCode = ""; // The user’s code
+let codeRanGood = false; // Your own function that returns true/false
+let consoleText = ""; // What was printed
let currentLesson = 0;
let lessonComplete = false;
@@ -23,11 +25,11 @@ function showLesson(index) {
document.getElementById('prev-lesson').disabled = index === 0;
document.getElementById('next-lesson').disabled = index === lessons.length - 1;
- console.log(isLessonDone(lesson.id));
+ //console.log(isLessonDone(lesson.id));
updateLessonStatus();
}
-function loadLessonContent(lesson){
+function loadLessonContent(lesson) {
document.getElementById('lesson-title').textContent = lesson.title;
document.getElementById('lesson-content').innerHTML = lesson.content;
}
@@ -39,10 +41,22 @@ document.getElementById('next-lesson').addEventListener('click', () => {
showLesson(currentLesson + 1);
});
-function checkLessonDone(outputText) {
- checkCurrentStep(outputText);
+function checkLessonDone() {
+ //consoleText = outputText; // Update console text
+ if (consoleText.includes("Error") || consoleText.includes("Exception")) {
+ codeRanGood = false;
+ } else {
+ codeRanGood = true;
+ }
+ console.log("codeRanGood ", codeRanGood);
+
+ //checkCurrentStep(outputText);
const lesson = lessons[currentLesson];
- const result = lesson.doneCondition(outputText);
+ const result = lesson.doneCondition({
+ code: mostRecentCode,
+ consoleText: consoleText,
+ codeRanGood: codeRanGood
+ });
if (result.done) {
markLessonDone(lesson.id);
}
@@ -60,7 +74,7 @@ function markLessonDone(lessonId) {
console.log(`Lesson ${lessonId} marked as done!`);
// For example:
localStorage.setItem(`lessonDone_${lessonId}`, 'true');
- logToConsole("✅ Task Completed! ✅");
+ logToConsole("✅ Task Completed! ✅", false);
updateLessonStatus();
}
@@ -118,8 +132,8 @@ function clearLessonProgress() {
}
-//clearLessonProgress(); // Clear progress on load for testing
-showLesson(3);
+clearLessonProgress(); // Clear progress on load for testing
+showLesson(7);
const consoleElement = document.getElementById("console");
const gameCanvas = document.getElementById("gameCanvas");
@@ -152,6 +166,7 @@ function startPyodideWorker() {
switch (event.data.type) {
case "console":
logToConsole(event.data.data);
+
break;
case "error":
logToConsole(`${event.data.message}`);
@@ -165,6 +180,10 @@ function startPyodideWorker() {
case "move":
move(event.data.data);
break;
+ case "execution_done":
+ console.log("Execution done");
+ checkLessonDone();
+ break;
}
};
@@ -218,7 +237,8 @@ function logToConsole(text, checkLesson = true) {
consoleElement.scrollTop = consoleElement.scrollHeight;
if (checkLesson && !text.includes("Welcome")) { // Don't check lesson completion for welcome message
- checkLessonDone(text);
+ consoleText = text; // Update console text
+ //checkLessonDone(text);
}
}
@@ -331,18 +351,18 @@ document.getElementById("compile-button").addEventListener("click", () => {
// Use the Monaco Editor instance to get the code
let code = monacoEditor.getValue(); // Get text from the editor
- console.log(code);
+ //console.log(code);
code = code.replace(/time\.sleep\(/g, "await time.sleep(");
- console.log(code);
+ //console.log(code);
consoleElement.innerHTML = "";
pyodideWorker.postMessage({
type: "execute",
code: code
});
-
- checkLessonDone(code);
+ mostRecentCode = code;
+ logToConsole("Compiling your code...", false);
});
diff --git a/pyodide-worker.js b/pyodide-worker.js
index 6581d2e..af64df1 100644
--- a/pyodide-worker.js
+++ b/pyodide-worker.js
@@ -12,14 +12,14 @@ async function initializePyodide() {
self.postMessage({ type: event, data: data });
});
-
+
// ✅ Expose sensor data to Python
self.pyodide.globals.set("get_sensor_data", (name) => {
- if (gameWorld == null){
+ if (gameWorld == null) {
return null;
}
-
+
//console.log(gameWorld.robots);
let robot = gameWorld.robots[0];
@@ -38,11 +38,11 @@ async function initializePyodide() {
self.pyodide.globals.set("get_robot_data", () => {
- if (gameWorld == null){
+ if (gameWorld == null) {
return null;
}
let robot = gameWorld.robots[0];
-
+
let robotData = {
"position": robot.body.position,
"angle": robot.body.angle,
@@ -141,7 +141,7 @@ self.onmessage = async (event) => {
self.postMessage({ type: "error", message: "Pyodide not initialized yet." });
return;
}
-
+
if (event.data.type === "sensor_update") {
// ✅ Update sensor data
Object.assign(sensorData, event.data.data);
@@ -158,5 +158,6 @@ self.onmessage = async (event) => {
} catch (error) {
self.postMessage({ type: "error", message: error.toString() });
}
+ self.postMessage({ type: "execution_done" });
}
};
diff --git a/style.css b/style.css
index 1be08f4..05248e5 100644
--- a/style.css
+++ b/style.css
@@ -50,6 +50,16 @@ header p {
/* gray-600 */
}
+code, pre {
+ font-family: Consolas, Menlo, Monaco, "Courier New", monospace;
+ background-color: inherit;
+ color: blue;
+ border: none;
+ padding: 0;
+ margin: 0;
+}
+
+
.button-group {
display: flex;
gap: 12px;
@@ -281,9 +291,9 @@ main {
}
-#lesson-box code {
+/* #lesson-box code {
background: #eee;
padding: 2px 4px;
border-radius: 4px;
font-family: monospace;
-}
\ No newline at end of file
+} */
\ No newline at end of file