added objectives to first robot lesson, locked compile button while executing, game world resets on compile & run
parent
9b702b6ff1
commit
8a0219500d
163
data/lessons.js
163
data/lessons.js
|
|
@ -77,71 +77,71 @@ export const lessons = [
|
||||||
"Print a boolean (True/False) to the console"
|
"Print a boolean (True/False) to the console"
|
||||||
],
|
],
|
||||||
doneCondition: (() => {
|
doneCondition: (() => {
|
||||||
// Matches print("something") or print('something')
|
// Matches print("something") or print('something')
|
||||||
const stringPrintRegex = /print\s*\(\s*(['"]).*?\1\s*\)/;
|
const stringPrintRegex = /print\s*\(\s*(['"]).*?\1\s*\)/;
|
||||||
|
|
||||||
// Matches print of float literal like 3.14, .5, -2.0, 1e-3
|
// Matches print of float literal like 3.14, .5, -2.0, 1e-3
|
||||||
const floatPrintRegex = /print\s*\(\s*[-+]?(?:\d+\.\d*|\.\d+|\d+[eE][-+]?\d+)\s*\)/;
|
const floatPrintRegex = /print\s*\(\s*[-+]?(?:\d+\.\d*|\.\d+|\d+[eE][-+]?\d+)\s*\)/;
|
||||||
|
|
||||||
// Matches print of int literal like 3, -42 (excluding floats)
|
// Matches print of int literal like 3, -42 (excluding floats)
|
||||||
const intPrintRegex = /print\s*\(\s*[-+]?\d+\s*\)/;
|
const intPrintRegex = /print\s*\(\s*[-+]?\d+\s*\)/;
|
||||||
|
|
||||||
// Matches print(True) or print(False), case-insensitive
|
// Matches print(True) or print(False), case-insensitive
|
||||||
const boolPrintRegex = /print\s*\(\s*(True|False)\s*\)/i;
|
const boolPrintRegex = /print\s*\(\s*(True|False)\s*\)/i;
|
||||||
|
|
||||||
return ({ code, codeRanGood }) => {
|
return ({ code, codeRanGood }) => {
|
||||||
if (!codeRanGood) {
|
if (!codeRanGood) {
|
||||||
return {
|
return {
|
||||||
done: false,
|
done: false,
|
||||||
hint: "Your code had an error — try fixing it and run again."
|
hint: "Your code had an error — try fixing it and run again."
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const progress = {
|
const progress = {
|
||||||
stringDone: stringPrintRegex.test(code),
|
stringDone: stringPrintRegex.test(code),
|
||||||
intDone: intPrintRegex.test(code),
|
intDone: intPrintRegex.test(code),
|
||||||
floatDone: floatPrintRegex.test(code),
|
floatDone: floatPrintRegex.test(code),
|
||||||
boolDone: boolPrintRegex.test(code),
|
boolDone: boolPrintRegex.test(code),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fix false positives where float also matches int
|
// Fix false positives where float also matches int
|
||||||
if (progress.floatDone && progress.intDone) {
|
if (progress.floatDone && progress.intDone) {
|
||||||
// Check if the float number has a dot or exponent; if not, it was a false int match
|
// Check if the float number has a dot or exponent; if not, it was a false int match
|
||||||
const matches = code.match(floatPrintRegex);
|
const matches = code.match(floatPrintRegex);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
const numbers = matches.map(m => m.match(/[-+]?(?:\d+\.\d*|\.\d+|\d+[eE][-+]?\d+)/)?.[0]);
|
const numbers = matches.map(m => m.match(/[-+]?(?:\d+\.\d*|\.\d+|\d+[eE][-+]?\d+)/)?.[0]);
|
||||||
for (const num of numbers) {
|
for (const num of numbers) {
|
||||||
if (num && !num.includes('.') && !num.toLowerCase().includes('e')) {
|
if (num && !num.includes('.') && !num.toLowerCase().includes('e')) {
|
||||||
// It's not a float, remove the float flag
|
// It's not a float, remove the float flag
|
||||||
progress.floatDone = false;
|
progress.floatDone = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const missing = [];
|
const missing = [];
|
||||||
if (!progress.stringDone) missing.push("string");
|
if (!progress.stringDone) missing.push("string");
|
||||||
if (!progress.floatDone) missing.push("float");
|
if (!progress.floatDone) missing.push("float");
|
||||||
if (!progress.intDone) missing.push("int");
|
if (!progress.intDone) missing.push("int");
|
||||||
if (!progress.boolDone) missing.push("boolean");
|
if (!progress.boolDone) missing.push("boolean");
|
||||||
|
|
||||||
let hint = "";
|
let hint = "";
|
||||||
if (missing.length > 0) {
|
if (missing.length > 0) {
|
||||||
hint = "I still need you to use print() with a ";
|
hint = "I still need you to use print() with a ";
|
||||||
hint += missing.length === 1
|
hint += missing.length === 1
|
||||||
? missing[0]
|
? missing[0]
|
||||||
: missing.slice(0, -1).join(", ") + " and " + missing[missing.length - 1];
|
: missing.slice(0, -1).join(", ") + " and " + missing[missing.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
const done = progress.stringDone && progress.intDone && progress.floatDone && progress.boolDone;
|
const done = progress.stringDone && progress.intDone && progress.floatDone && progress.boolDone;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
done,
|
done,
|
||||||
progressArray: Object.values(progress),
|
progressArray: Object.values(progress),
|
||||||
hint
|
hint
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
})()
|
})()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -872,59 +872,31 @@ robot.move(0) # Stop the robot
|
||||||
</code></pre>
|
</code></pre>
|
||||||
`,
|
`,
|
||||||
objectives: [
|
objectives: [
|
||||||
"Import the time module",
|
"Reach the first checkpoint",
|
||||||
"Print something",
|
"Reach the second checkpoint",
|
||||||
"Use time.sleep() to pause for an amount of time",
|
|
||||||
"Print something else after the pause"
|
"Code should complete without errors"
|
||||||
],
|
],
|
||||||
|
|
||||||
doneCondition: (() => {
|
doneCondition: (() => {
|
||||||
return ({ code, consoleText, codeRanGood }) => {
|
return ({ code, consoleText, codeRanGood, gameWorld }) => {
|
||||||
const progress = {
|
const progress = {
|
||||||
importedTime: false,
|
firstCheckpoint: gameWorld.waypointsReached[0],
|
||||||
printedBefore: false,
|
secondCheckpoint: gameWorld.waypointsReached[1],
|
||||||
usedSleep: false,
|
codeRanGood: codeRanGood,
|
||||||
printedAfter: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!codeRanGood) {
|
if (!codeRanGood) {
|
||||||
return { done: false, hint: "" };
|
return { done: false, hint: "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Check for "import time"
|
|
||||||
const importRegex = /^\s*import\s+time\b/m;
|
|
||||||
progress.importedTime = importRegex.test(code);
|
|
||||||
|
|
||||||
// 2. Match all print(...) calls
|
|
||||||
const printRegex = /print\s*\(.*?\)/g;
|
|
||||||
const printMatches = [...code.matchAll(printRegex)];
|
|
||||||
|
|
||||||
// 3. Match time.sleep(...)
|
|
||||||
const sleepRegex = /time\.sleep\s*\(\s*[\d.]+\s*\)/;
|
|
||||||
const sleepMatch = sleepRegex.exec(code);
|
|
||||||
progress.usedSleep = !!sleepMatch;
|
|
||||||
|
|
||||||
// 4. Handle print position logic
|
|
||||||
if (printMatches.length > 0) {
|
|
||||||
// If there's no sleep, we just say "they printed something" — early lesson support
|
|
||||||
if (!sleepMatch) {
|
|
||||||
progress.printedBefore = true; // consider *any* print valid before sleep
|
|
||||||
} else {
|
|
||||||
const sleepIndex = sleepMatch.index;
|
|
||||||
for (const m of printMatches) {
|
|
||||||
if (m.index < sleepIndex) progress.printedBefore = true;
|
|
||||||
if (m.index > sleepIndex) progress.printedAfter = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Build hint
|
// 5. Build hint
|
||||||
const missing = [];
|
const missing = [];
|
||||||
if (!progress.importedTime) missing.push("import the time module");
|
if (!progress.firstCheckpoint) missing.push("reach the first checkpoint");
|
||||||
if (!progress.printedBefore) missing.push("print something before sleeping");
|
if (!progress.secondCheckpoint) missing.push("reach the second checkpoint");
|
||||||
if (!progress.usedSleep) missing.push("use time.sleep()");
|
|
||||||
if (!progress.printedAfter && progress.usedSleep)
|
|
||||||
missing.push("print something after sleeping");
|
|
||||||
|
|
||||||
let hint = "";
|
let hint = "";
|
||||||
if (missing.length === 1) {
|
if (missing.length === 1) {
|
||||||
|
|
@ -935,10 +907,9 @@ robot.move(0) # Stop the robot
|
||||||
|
|
||||||
return {
|
return {
|
||||||
done:
|
done:
|
||||||
progress.importedTime &&
|
progress.firstCheckpoint &&
|
||||||
progress.printedBefore &&
|
progress.secondCheckpoint &&
|
||||||
progress.usedSleep &&
|
progress.codeRanGood,
|
||||||
progress.printedAfter,
|
|
||||||
progressArray: Object.values(progress),
|
progressArray: Object.values(progress),
|
||||||
hint,
|
hint,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,33 @@
|
||||||
{
|
{
|
||||||
"position": {
|
"position": {
|
||||||
"x": 420,
|
"x": 420,
|
||||||
"y": 600
|
"y": 200
|
||||||
|
},
|
||||||
|
"vertices": [
|
||||||
|
{
|
||||||
|
"x": -50,
|
||||||
|
"y": -50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 50,
|
||||||
|
"y": -50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 50,
|
||||||
|
"y": 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": -50,
|
||||||
|
"y": 50
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"strokeColor": "#0000FF",
|
||||||
|
"fillColor": "#0000CC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": {
|
||||||
|
"x": 50,
|
||||||
|
"y": 200
|
||||||
},
|
},
|
||||||
"vertices": [
|
"vertices": [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
26
game.js
26
game.js
|
|
@ -92,7 +92,8 @@ function checkLessonDone() {
|
||||||
const result = lesson.doneCondition({
|
const result = lesson.doneCondition({
|
||||||
code: mostRecentCode,
|
code: mostRecentCode,
|
||||||
consoleText: consoleText,
|
consoleText: consoleText,
|
||||||
codeRanGood: codeRanGood
|
codeRanGood: codeRanGood,
|
||||||
|
gameWorld: gameWorld
|
||||||
});
|
});
|
||||||
if (result.done) {
|
if (result.done) {
|
||||||
markLessonDone(lesson.id);
|
markLessonDone(lesson.id);
|
||||||
|
|
@ -220,7 +221,7 @@ function toggleObjective(index, completed = true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//clearLessonProgress(); // Clear progress on load for testing
|
//clearLessonProgress(); // Clear progress on load for testing
|
||||||
showLesson(1);
|
showLesson(9);
|
||||||
|
|
||||||
const consoleElement = document.getElementById("console");
|
const consoleElement = document.getElementById("console");
|
||||||
const gameCanvas = document.getElementById("gameCanvas");
|
const gameCanvas = document.getElementById("gameCanvas");
|
||||||
|
|
@ -269,6 +270,7 @@ function startPyodideWorker() {
|
||||||
break;
|
break;
|
||||||
case "execution_done":
|
case "execution_done":
|
||||||
console.log("Execution done");
|
console.log("Execution done");
|
||||||
|
document.getElementById('compile-button').disabled = false;
|
||||||
checkLessonDone();
|
checkLessonDone();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -355,6 +357,12 @@ function togglePause() {
|
||||||
document.getElementById("pause-button").innerText = paused ? "Resume" : "Pause";
|
document.getElementById("pause-button").innerText = paused ? "Resume" : "Pause";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetGameWorld() {
|
||||||
|
robots = createInitialRobots();
|
||||||
|
gameWorld.reset(robots["player"]);
|
||||||
|
pyodideWorker.postMessage({ type: "interrupt" });
|
||||||
|
}
|
||||||
|
|
||||||
// ✅ Reset Function (Fixed)
|
// ✅ Reset Function (Fixed)
|
||||||
function resetGame() {
|
function resetGame() {
|
||||||
// Terminate the worker
|
// Terminate the worker
|
||||||
|
|
@ -400,11 +408,12 @@ function gameLoop(timestamp) {
|
||||||
|
|
||||||
gameWorld.update();
|
gameWorld.update();
|
||||||
gameWorld.draw(ctx);
|
gameWorld.draw(ctx);
|
||||||
if (gameWorld.checkPlayerCompletedTask()) {
|
|
||||||
logToConsole("✅ Task Completed! ✅");
|
// if (gameWorld.checkPlayerCompletedTask()) {
|
||||||
togglePause();
|
// logToConsole("✅ Task Completed! ✅");
|
||||||
gameWorld.currentLevel++;
|
// togglePause();
|
||||||
}
|
// gameWorld.currentLevel++;
|
||||||
|
// }
|
||||||
|
|
||||||
pyodideWorker.postMessage({
|
pyodideWorker.postMessage({
|
||||||
type: "game_state",
|
type: "game_state",
|
||||||
|
|
@ -435,7 +444,8 @@ function updateSensorData() {
|
||||||
|
|
||||||
document.getElementById("compile-button").addEventListener("click", () => {
|
document.getElementById("compile-button").addEventListener("click", () => {
|
||||||
if (paused) return;
|
if (paused) return;
|
||||||
|
document.getElementById('compile-button').disabled = true;
|
||||||
|
resetGameWorld();
|
||||||
// Use the Monaco Editor instance to get the code
|
// Use the Monaco Editor instance to get the code
|
||||||
let code = monacoEditor.getValue(); // Get text from the editor
|
let code = monacoEditor.getValue(); // Get text from the editor
|
||||||
//console.log(code);
|
//console.log(code);
|
||||||
|
|
|
||||||
55
gameworld.js
55
gameworld.js
|
|
@ -14,6 +14,7 @@ export class GameWorld {
|
||||||
this.currentLevel = 0;
|
this.currentLevel = 0;
|
||||||
|
|
||||||
this.waypoints = [];
|
this.waypoints = [];
|
||||||
|
this.waypointsReached = [];
|
||||||
this.obstacles = [];
|
this.obstacles = [];
|
||||||
this.robots = [];
|
this.robots = [];
|
||||||
|
|
||||||
|
|
@ -28,6 +29,7 @@ export class GameWorld {
|
||||||
this.robots = []
|
this.robots = []
|
||||||
this.obstacles = []
|
this.obstacles = []
|
||||||
this.waypoints = [];
|
this.waypoints = [];
|
||||||
|
this.waypointsReached = [];
|
||||||
Matter.World.clear(this.world); // Clear the world without resetting the engine
|
Matter.World.clear(this.world); // Clear the world without resetting the engine
|
||||||
|
|
||||||
let level = this.levelData[this.currentLevel];
|
let level = this.levelData[this.currentLevel];
|
||||||
|
|
@ -51,7 +53,9 @@ export class GameWorld {
|
||||||
let obstacle = level.waypoints[i];
|
let obstacle = level.waypoints[i];
|
||||||
console.log("Adding waypoint:", obstacle);
|
console.log("Adding waypoint:", obstacle);
|
||||||
this.addWaypoint(obstacle.vertices, obstacle.position, obstacle.strokeColor, obstacle.fillColor);
|
this.addWaypoint(obstacle.vertices, obstacle.position, obstacle.strokeColor, obstacle.fillColor);
|
||||||
|
this.waypointsReached.push(false); // Initialize as not reached
|
||||||
}
|
}
|
||||||
|
console.log(level.waypointsReached)
|
||||||
|
|
||||||
// this.addObstacle([
|
// this.addObstacle([
|
||||||
// { x: -100, y: -100 }, // Vertex 1
|
// { x: -100, y: -100 }, // Vertex 1
|
||||||
|
|
@ -77,7 +81,19 @@ export class GameWorld {
|
||||||
this.robots[id].update(this);
|
this.robots[id].update(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < this.waypoints.length; i++) {
|
||||||
|
if (this.waypointsReached[i]) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
let waypoint = this.waypoints[i];
|
||||||
|
let playerPos = this.robots[0].body.position;
|
||||||
|
let waypointBounds = waypoint.bounds;
|
||||||
|
if (Matter.Bounds.contains(waypointBounds, playerPos)) {
|
||||||
|
console.log("Player is inside the waypoint's bounding box.");
|
||||||
|
this.waypointsReached[i] = true; // Mark this waypoint as reached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//this.checkPlayerCompletedTask();
|
//this.checkPlayerCompletedTask();
|
||||||
|
|
||||||
|
|
@ -86,17 +102,21 @@ export class GameWorld {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Needs to be updated to handle different win conditions
|
waypointsReached() {
|
||||||
checkPlayerCompletedTask() {
|
return this.waypointsReached;
|
||||||
let playerPos = this.robots[0].body.position;
|
|
||||||
let waypointBounds = this.waypoints[0].bounds;
|
|
||||||
if (Matter.Bounds.contains(waypointBounds, playerPos)) {
|
|
||||||
console.log("Player is inside the waypoint's bounding box.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Needs to be updated to handle different win conditions
|
||||||
|
// checkPlayerCompletedTask() {
|
||||||
|
// let playerPos = this.robots[0].body.position;
|
||||||
|
// let waypointBounds = this.waypoints[0].bounds;
|
||||||
|
// if (Matter.Bounds.contains(waypointBounds, playerPos)) {
|
||||||
|
// console.log("Player is inside the waypoint's bounding box.");
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
addWaypoint(vertices, position = { x: 0, y: 0 }, strokeColor = "yellow", fillColor = "yellow") {
|
addWaypoint(vertices, position = { x: 0, y: 0 }, strokeColor = "yellow", fillColor = "yellow") {
|
||||||
// Convert the polygon points into a Matter.js body
|
// Convert the polygon points into a Matter.js body
|
||||||
let body = Matter.Bodies.fromVertices(position.x, position.y, [vertices], {
|
let body = Matter.Bodies.fromVertices(position.x, position.y, [vertices], {
|
||||||
|
|
@ -167,22 +187,29 @@ export class GameWorld {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Draw Waypoints
|
// Draw Waypoints
|
||||||
this.waypoints.forEach(body => {
|
for (let w = 0; w < this.waypoints.length; w++) {
|
||||||
|
let body = this.waypoints[w];
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
let vertices = body.vertices;
|
let vertices = body.vertices;
|
||||||
ctx.moveTo(vertices[0].x, vertices[0].y);
|
ctx.moveTo(vertices[0].x, vertices[0].y);
|
||||||
for (let i = 1; i < vertices.length; i++) {
|
for (let i = 1; i < vertices.length; i++) {
|
||||||
ctx.lineTo(vertices[i].x, vertices[i].y);
|
ctx.lineTo(vertices[i].x, vertices[i].y);
|
||||||
}
|
}
|
||||||
ctx.fillStyle = body.fillColor;;
|
|
||||||
|
|
||||||
ctx.strokeStyle = body.strokeColor;
|
if (this.waypointsReached[w]) {
|
||||||
|
ctx.globalAlpha = 0.05; // Applies to all drawing
|
||||||
|
ctx.fillStyle = "green"; // Color for reached waypoints
|
||||||
|
ctx.strokeStyle = "rgba(0, 128, 0, 0.2)"; // green with 80% opacity
|
||||||
|
} else {
|
||||||
|
ctx.globalAlpha = 0.2; // Applies to all drawing
|
||||||
|
ctx.fillStyle = body.fillColor; // Default color for waypoints
|
||||||
|
ctx.strokeStyle = body.strokeColor;
|
||||||
|
}
|
||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
ctx.globalAlpha = 0.2; // Applies to all drawing
|
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
ctx.globalAlpha = 1.0; // Reset after if needed
|
ctx.globalAlpha = 1.0; // Reset after if needed
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
});
|
}
|
||||||
|
|
||||||
this.robots.forEach(robot => {
|
this.robots.forEach(robot => {
|
||||||
let body = robot.body; // Get the Matter.js body from the robot object
|
let body = robot.body; // Get the Matter.js body from the robot object
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
importScripts("https://cdn.jsdelivr.net/pyodide/v0.23.4/full/pyodide.js");
|
importScripts("https://cdn.jsdelivr.net/pyodide/v0.27.7/full/pyodide.js");
|
||||||
|
|
||||||
let sensorData = {}; // ✅ Store sensor values
|
let sensorData = {}; // ✅ Store sensor values
|
||||||
let gameWorld = null;
|
let gameWorld = null;
|
||||||
|
|
||||||
async function initializePyodide() {
|
async function initializePyodide() {
|
||||||
self.pyodide = await loadPyodide({
|
self.pyodide = await loadPyodide({
|
||||||
indexURL: "https://cdn.jsdelivr.net/pyodide/v0.23.4/full/"
|
indexURL: "https://cdn.jsdelivr.net/pyodide/v0.27.7/full/"
|
||||||
});
|
});
|
||||||
|
console.log("Pyodide loaded:", self.pyodide.version);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.pyodide.globals.set("send_to_main", (event, data) => {
|
self.pyodide.globals.set("send_to_main", (event, data) => {
|
||||||
self.postMessage({ type: event, data: data });
|
self.postMessage({ type: event, data: data });
|
||||||
|
|
@ -26,10 +29,10 @@ async function initializePyodide() {
|
||||||
//console.log(robot);
|
//console.log(robot);
|
||||||
let sensorArray = robot.sensors || []; // Assuming `sensors` is an array inside the robot object
|
let sensorArray = robot.sensors || []; // Assuming `sensors` is an array inside the robot object
|
||||||
sensorData = sensorArray.map(sensor => ({
|
sensorData = sensorArray.map(sensor => ({
|
||||||
"type": sensor.type, // Individual sensor's type
|
"type": sensor.type, // Individual sensor's type
|
||||||
"angle": sensor.angle, // Individual sensor's angle
|
"angle": sensor.angle, // Individual sensor's angle
|
||||||
"distance": sensor.distance, // Individual sensor's distance
|
"distance": sensor.distance, // Individual sensor's distance
|
||||||
"hitpoint": sensor.hitpoint // Whatever other attributes you need
|
"hitpoint": sensor.hitpoint // Whatever other attributes you need
|
||||||
}));
|
}));
|
||||||
//console.log(sensorData["x"]);
|
//console.log(sensorData["x"]);
|
||||||
sensorData = JSON.stringify(sensorData);
|
sensorData = JSON.stringify(sensorData);
|
||||||
|
|
@ -139,6 +142,8 @@ async def async_sleep(seconds):
|
||||||
|
|
||||||
|
|
||||||
time.sleep = async_sleep # ✅ Monkey-patch time.sleep()
|
time.sleep = async_sleep # ✅ Monkey-patch time.sleep()
|
||||||
|
|
||||||
|
|
||||||
`);
|
`);
|
||||||
|
|
||||||
self.postMessage({ type: "ready" }); // ✅ Notify main thread that Pyodide is ready
|
self.postMessage({ type: "ready" }); // ✅ Notify main thread that Pyodide is ready
|
||||||
|
|
@ -146,6 +151,11 @@ time.sleep = async_sleep # ✅ Monkey-patch time.sleep()
|
||||||
|
|
||||||
initializePyodide();
|
initializePyodide();
|
||||||
|
|
||||||
|
// Add this function to trigger interrupts
|
||||||
|
function interruptExecution() {
|
||||||
|
interruptBuffer[0] = 2; // 2 is the magic number for KeyboardInterrupt
|
||||||
|
}
|
||||||
|
|
||||||
self.onmessage = async (event) => {
|
self.onmessage = async (event) => {
|
||||||
if (!self.pyodide) {
|
if (!self.pyodide) {
|
||||||
self.postMessage({ type: "error", message: "Pyodide not initialized yet." });
|
self.postMessage({ type: "error", message: "Pyodide not initialized yet." });
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue