added individual objectives
parent
9bbc8592e0
commit
05dd8cb6a3
253
data/lessons.js
253
data/lessons.js
|
|
@ -13,12 +13,16 @@ export const lessons = [
|
||||||
<li>You should see "Hello World" printed in the output area</li>
|
<li>You should see "Hello World" printed in the output area</li>
|
||||||
</ol>
|
</ol>
|
||||||
`,
|
`,
|
||||||
|
objectives: [
|
||||||
|
"Print \"Hello World\" to the console"
|
||||||
|
],
|
||||||
doneCondition: (() => {
|
doneCondition: (() => {
|
||||||
|
|
||||||
|
|
||||||
|
return ({ lesson, code, consoleText, codeRanGood }) => {
|
||||||
const progress = {
|
const progress = {
|
||||||
stringDone: false
|
stringDone: false
|
||||||
};
|
};
|
||||||
|
|
||||||
return ({ code, consoleText, codeRanGood }) => {
|
|
||||||
if (codeRanGood && !progress.stringDone && consoleText.includes("Hello World")) {
|
if (codeRanGood && !progress.stringDone && consoleText.includes("Hello World")) {
|
||||||
progress.stringDone = true;
|
progress.stringDone = true;
|
||||||
}
|
}
|
||||||
|
|
@ -37,6 +41,7 @@ export const lessons = [
|
||||||
|
|
||||||
return {
|
return {
|
||||||
done: progress.stringDone,
|
done: progress.stringDone,
|
||||||
|
progressArray: Object.values(progress),
|
||||||
hint
|
hint
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -63,7 +68,21 @@ export const lessons = [
|
||||||
</ol>
|
</ol>
|
||||||
<p>Click the "Run" button to execute your code</p>
|
<p>Click the "Run" button to execute your code</p>
|
||||||
`,
|
`,
|
||||||
|
objectives: [
|
||||||
|
"Print a string to the console",
|
||||||
|
"Print an int to the console",
|
||||||
|
"Print a float to the console",
|
||||||
|
"Print a boolean (True/False) to the console"
|
||||||
|
],
|
||||||
doneCondition: (() => {
|
doneCondition: (() => {
|
||||||
|
|
||||||
|
|
||||||
|
const stringRegex = /print\s*\(\s*(['"]).*?\1\s*\)/;
|
||||||
|
const intRegex = /(?<![\d.])[-+]?\d+(?![\d.])/;
|
||||||
|
const floatRegex = /[-+]?(?:\d+\.\d*|\.\d+)(?:[eE][-+]?\d+)?/;
|
||||||
|
const boolRegex = /\b(True|False|true|false)\b/;
|
||||||
|
|
||||||
|
return ({ code, consoleText, codeRanGood }) => {
|
||||||
const progress = {
|
const progress = {
|
||||||
stringDone: false,
|
stringDone: false,
|
||||||
intDone: false,
|
intDone: false,
|
||||||
|
|
@ -71,13 +90,6 @@ export const lessons = [
|
||||||
boolDone: false,
|
boolDone: false,
|
||||||
// syntaxErrorDone: false, // optional
|
// syntaxErrorDone: false, // optional
|
||||||
};
|
};
|
||||||
|
|
||||||
const stringRegex = /(["'])(?:(?=(\\?))\2.)*?\1/;
|
|
||||||
const intRegex = /(?<![\d.])[-+]?\d+(?![\d.])/;
|
|
||||||
const floatRegex = /[-+]?(?:\d+\.\d*|\.\d+)(?:[eE][-+]?\d+)?/;
|
|
||||||
const boolRegex = /\b(True|False|true|false)\b/;
|
|
||||||
|
|
||||||
return ({ code, consoleText, codeRanGood }) => {
|
|
||||||
if (!codeRanGood) {
|
if (!codeRanGood) {
|
||||||
return {
|
return {
|
||||||
done: false,
|
done: false,
|
||||||
|
|
@ -85,7 +97,7 @@ export const lessons = [
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!progress.stringDone && stringRegex.test(consoleText)) {
|
if (!progress.stringDone && stringRegex.test(code)) {
|
||||||
progress.stringDone = true;
|
progress.stringDone = true;
|
||||||
}
|
}
|
||||||
if (!progress.floatDone && floatRegex.test(consoleText)) {
|
if (!progress.floatDone && floatRegex.test(consoleText)) {
|
||||||
|
|
@ -99,6 +111,7 @@ export const lessons = [
|
||||||
}
|
}
|
||||||
|
|
||||||
const missing = [];
|
const missing = [];
|
||||||
|
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");
|
||||||
|
|
@ -112,8 +125,12 @@ export const lessons = [
|
||||||
hint += missing.slice(0, -1).join(", ") + " and " + missing[missing.length - 1];
|
hint += missing.slice(0, -1).join(", ") + " and " + missing[missing.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
const done = progress.intDone && progress.floatDone && progress.boolDone;
|
const done = progress.stringDone && progress.intDone && progress.floatDone && progress.boolDone;
|
||||||
return { done, hint };
|
return {
|
||||||
|
done,
|
||||||
|
progressArray: Object.values(progress),
|
||||||
|
hint
|
||||||
|
};
|
||||||
};
|
};
|
||||||
})()
|
})()
|
||||||
|
|
||||||
|
|
@ -133,8 +150,17 @@ export const lessons = [
|
||||||
<li>Division: <code>print(20 / 5)</code></li>
|
<li>Division: <code>print(20 / 5)</code></li>
|
||||||
</ol>
|
</ol>
|
||||||
`,
|
`,
|
||||||
|
objectives: [
|
||||||
|
"Do some addition",
|
||||||
|
"Do some subtraction",
|
||||||
|
"Do some multiplication",
|
||||||
|
"Do some division",
|
||||||
|
],
|
||||||
doneCondition: (() => {
|
doneCondition: (() => {
|
||||||
// Persistent tracking object inside closure
|
// Persistent tracking object inside closure
|
||||||
|
|
||||||
|
|
||||||
|
return ({ code, consoleText, codeRanGood }) => {
|
||||||
const progress = {
|
const progress = {
|
||||||
addDone: false,
|
addDone: false,
|
||||||
subDone: false,
|
subDone: false,
|
||||||
|
|
@ -143,9 +169,6 @@ export const lessons = [
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return ({ code, consoleText, codeRanGood }) => {
|
|
||||||
if (!codeRanGood) {
|
if (!codeRanGood) {
|
||||||
return {
|
return {
|
||||||
done: false,
|
done: false,
|
||||||
|
|
@ -190,7 +213,11 @@ export const lessons = [
|
||||||
|
|
||||||
|
|
||||||
const done = progress.addDone && progress.subDone && progress.mulDone && progress.divDone;
|
const done = progress.addDone && progress.subDone && progress.mulDone && progress.divDone;
|
||||||
return { done, hint };
|
return {
|
||||||
|
done,
|
||||||
|
progressArray: Object.values(progress),
|
||||||
|
hint
|
||||||
|
};
|
||||||
};
|
};
|
||||||
})()
|
})()
|
||||||
},
|
},
|
||||||
|
|
@ -211,28 +238,19 @@ export const lessons = [
|
||||||
<li>Print the value of bob: <code>print(bob)</code></
|
<li>Print the value of bob: <code>print(bob)</code></
|
||||||
</ol>
|
</ol>
|
||||||
`,
|
`,
|
||||||
steps: [
|
objectives: [
|
||||||
{
|
"Initialize a variable with a value",
|
||||||
content: `<p>First, try printing an addition: <code>print(2 + 3)</code></p>`,
|
"Print the variable using print()"
|
||||||
doneCondition: (text) => text.includes("5"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: `<p>Nice! Now try subtraction: <code>print(5 - 2)</code></p>`,
|
|
||||||
doneCondition: (text) => text.includes("3"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: `<p>Now try multiplication: <code>print(4 * 2)</code></p>`,
|
|
||||||
doneCondition: (text) => text.includes("8"),
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
doneCondition: (() => {
|
doneCondition: (() => {
|
||||||
|
|
||||||
|
|
||||||
|
return ({ code, consoleText, codeRanGood }) => {
|
||||||
const progress = {
|
const progress = {
|
||||||
varCreated: false,
|
varCreated: false,
|
||||||
varPrinted: false,
|
varPrinted: false,
|
||||||
varName: null,
|
varName: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
return ({ code, consoleText, codeRanGood }) => {
|
|
||||||
if (!codeRanGood) {
|
if (!codeRanGood) {
|
||||||
return {
|
return {
|
||||||
done: false,
|
done: false,
|
||||||
|
|
@ -274,7 +292,11 @@ export const lessons = [
|
||||||
}
|
}
|
||||||
|
|
||||||
const done = progress.varCreated && progress.varPrinted;
|
const done = progress.varCreated && progress.varPrinted;
|
||||||
return { done, hint };
|
return {
|
||||||
|
done,
|
||||||
|
progressArray: Object.values(progress),
|
||||||
|
hint
|
||||||
|
};
|
||||||
};
|
};
|
||||||
})()
|
})()
|
||||||
},
|
},
|
||||||
|
|
@ -297,72 +319,111 @@ print(bob)
|
||||||
<p>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.</p>
|
<p>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.</p>
|
||||||
<p>Give it a try.</p>
|
<p>Give it a try.</p>
|
||||||
`,
|
`,
|
||||||
steps: [
|
objectives: [
|
||||||
{
|
"Initialize a variable with a value",
|
||||||
content: `<p>First, try printing an addition: <code>print(2 + 3)</code></p>`,
|
"Print the variable using print()",
|
||||||
doneCondition: (text) => text.includes("5"),
|
"Alter the value of the variable",
|
||||||
},
|
"Print the variable again using print()",
|
||||||
{
|
|
||||||
content: `<p>Nice! Now try subtraction: <code>print(5 - 2)</code></p>`,
|
|
||||||
doneCondition: (text) => text.includes("3"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: `<p>Now try multiplication: <code>print(4 * 2)</code></p>`,
|
|
||||||
doneCondition: (text) => text.includes("8"),
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
doneCondition: (() => {
|
doneCondition: (() => {
|
||||||
|
|
||||||
|
|
||||||
|
return ({ code, consoleText, codeRanGood }) => {
|
||||||
const progress = {
|
const progress = {
|
||||||
varCreated: false,
|
varCreated: false,
|
||||||
varPrinted: false,
|
varPrinted: false,
|
||||||
varArithmeticDone: false,
|
varArithmeticDone: false,
|
||||||
varPrintedTwice: false,
|
varPrintedTwice: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
return ({ code, consoleText, codeRanGood }) => {
|
|
||||||
if (!codeRanGood) {
|
if (!codeRanGood) {
|
||||||
return {
|
return {
|
||||||
done: false,
|
done: false,
|
||||||
|
progressArray: Object.values(progress),
|
||||||
hint: ""
|
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
|
|
||||||
|
|
||||||
const match = code.match(assignRegex);
|
const assignRegex = /^(\w+)\s*=\s*.+$/m;
|
||||||
if (!match) return false;
|
const assignMatch = assignRegex.exec(code);
|
||||||
|
if (!assignMatch) {
|
||||||
const varName = match[1];
|
return {
|
||||||
const dynamicPrint1 = new RegExp(`print\\(\\s*${varName}\\s*\\)`);
|
done: false,
|
||||||
const dynamicMath = new RegExp(`${varName}\\s*=\\s*${varName}\\s*[+\\-*/]\\s*[\\d'"]`);
|
progressArray: Object.values(progress),
|
||||||
const dynamicPrint2 = new RegExp(`print\\(\\s*${varName}\\s*\\)`, 'g');
|
hint: "I still need you to create a variable"
|
||||||
|
};
|
||||||
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;
|
const varName = assignMatch[1];
|
||||||
return { done, hint };
|
|
||||||
|
const printRegex = new RegExp(`print\\s*\\(\\s*${varName}\\s*\\)`, "g");
|
||||||
|
const assignAllRegex = new RegExp(`^${varName}\\s*=.+$`, "gm");
|
||||||
|
const arithmeticRegex = new RegExp(
|
||||||
|
`^${varName}\\s*=\\s*${varName}\\s*[+\\-*/]\\s*.+$|^${varName}\\s*[+\\-*/]=\\s*.+$`,
|
||||||
|
"gm"
|
||||||
|
);
|
||||||
|
|
||||||
|
progress.varCreated = true;
|
||||||
|
|
||||||
|
const printMatches = [...code.matchAll(printRegex)];
|
||||||
|
progress.varPrinted = printMatches.length > 0;
|
||||||
|
if (!progress.varPrinted) {
|
||||||
|
return {
|
||||||
|
done: false,
|
||||||
|
progressArray: Object.values(progress),
|
||||||
|
hint: "I still need you to print the variable"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
progress.varArithmeticDone = arithmeticRegex.test(code);
|
||||||
|
if (!progress.varArithmeticDone) {
|
||||||
|
return {
|
||||||
|
done: false,
|
||||||
|
progressArray: Object.values(progress),
|
||||||
|
|
||||||
|
hint: "I still need you to alter the variable (e.g. with arithmetic)"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const assignMatches = [...code.matchAll(assignAllRegex)];
|
||||||
|
if (assignMatches.length < 2) {
|
||||||
|
return {
|
||||||
|
done: false,
|
||||||
|
progressArray: Object.values(progress),
|
||||||
|
hint: "I still need you to alter the variable before printing it again"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug logs
|
||||||
|
console.log("Variable:", varName);
|
||||||
|
console.log("Assignments found:", assignMatches.length);
|
||||||
|
assignMatches.forEach((m, i) =>
|
||||||
|
console.log(`Assign #${i}: index=${m.index}, text=${m[0].trim()}`)
|
||||||
|
);
|
||||||
|
console.log("Prints found:", printMatches.length);
|
||||||
|
printMatches.forEach((m, i) =>
|
||||||
|
console.log(`Print #${i}: index=${m.index}, text=${code.slice(m.index, m.index + 20)}`)
|
||||||
|
);
|
||||||
|
console.log("Arithmetic detected:", progress.varArithmeticDone);
|
||||||
|
|
||||||
|
const secondAssignIndex = assignMatches[1].index;
|
||||||
|
progress.varPrintedTwice = printMatches.some((m) => m.index > secondAssignIndex);
|
||||||
|
|
||||||
|
if (!progress.varPrintedTwice) {
|
||||||
|
return {
|
||||||
|
done: false,
|
||||||
|
progressArray: Object.values(progress),
|
||||||
|
hint: "I still need you to print the variable a second time after altering it",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
done: true,
|
||||||
|
progressArray: Object.values(progress),
|
||||||
|
hint: "",
|
||||||
|
};
|
||||||
};
|
};
|
||||||
})()
|
})()
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'lesson6',
|
id: 'lesson6',
|
||||||
|
|
@ -394,15 +455,20 @@ if num == 10:
|
||||||
print("num is equal to 10")
|
print("num is equal to 10")
|
||||||
</code></pre>
|
</code></pre>
|
||||||
`,
|
`,
|
||||||
|
objectives: [
|
||||||
|
"Initialize a variable with a value",
|
||||||
|
"Create an if statement to check a condition", ,
|
||||||
|
"Print a message based on the condition",
|
||||||
|
],
|
||||||
|
|
||||||
doneCondition: (() => {
|
doneCondition: (() => {
|
||||||
|
|
||||||
|
return ({ code, consoleText, codeRanGood }) => {
|
||||||
const progress = {
|
const progress = {
|
||||||
varCreated: false,
|
varCreated: false,
|
||||||
ifStatement: false,
|
ifStatement: false,
|
||||||
printedSomething: false,
|
printedSomething: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
return ({ code, consoleText, codeRanGood }) => {
|
|
||||||
if (!codeRanGood) {
|
if (!codeRanGood) {
|
||||||
return {
|
return {
|
||||||
done: false,
|
done: false,
|
||||||
|
|
@ -434,7 +500,11 @@ if num == 10:
|
||||||
}
|
}
|
||||||
|
|
||||||
const done = progress.varCreated && progress.ifStatement && progress.printedSomething;
|
const done = progress.varCreated && progress.ifStatement && progress.printedSomething;
|
||||||
return { done, hint };
|
return {
|
||||||
|
done,
|
||||||
|
progressArray: Object.values(progress),
|
||||||
|
hint
|
||||||
|
};
|
||||||
};
|
};
|
||||||
})()
|
})()
|
||||||
|
|
||||||
|
|
@ -459,8 +529,17 @@ else:
|
||||||
<p>You can chain as many <code>elif</code> statements as you like, but only one <code>else</code> at the end.</p>
|
<p>You can chain as many <code>elif</code> statements as you like, but only one <code>else</code> at the end.</p>
|
||||||
<p>Try it for yourself:</p>
|
<p>Try it for yourself:</p>
|
||||||
`,
|
`,
|
||||||
|
objectives: [
|
||||||
|
"Initialize a variable with a value",
|
||||||
|
"Create an if statement to check a condition", ,
|
||||||
|
"Create an elif statement to check another condition",
|
||||||
|
"Create an else statement to catch all other conditions",
|
||||||
|
"Print a message based on each of the conditions",
|
||||||
|
],
|
||||||
doneCondition: (() => {
|
doneCondition: (() => {
|
||||||
|
|
||||||
|
return ({ code, consoleText, codeRanGood }) => {
|
||||||
|
|
||||||
const progress = {
|
const progress = {
|
||||||
varCreated: false,
|
varCreated: false,
|
||||||
ifStatement: false,
|
ifStatement: false,
|
||||||
|
|
@ -468,8 +547,6 @@ else:
|
||||||
elseStatement: false,
|
elseStatement: false,
|
||||||
threeDistinctPrints: false,
|
threeDistinctPrints: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
return ({ code, consoleText, codeRanGood }) => {
|
|
||||||
if (!codeRanGood) {
|
if (!codeRanGood) {
|
||||||
return { done: false, hint: "" };
|
return { done: false, hint: "" };
|
||||||
}
|
}
|
||||||
|
|
@ -536,7 +613,11 @@ else:
|
||||||
const done = progress.varCreated && progress.ifStatement && progress.elifStatement &&
|
const done = progress.varCreated && progress.ifStatement && progress.elifStatement &&
|
||||||
progress.elseStatement && progress.threeDistinctPrints;
|
progress.elseStatement && progress.threeDistinctPrints;
|
||||||
|
|
||||||
return { done, hint };
|
return {
|
||||||
|
done,
|
||||||
|
progressArray: Object.values(progress),
|
||||||
|
hint
|
||||||
|
};
|
||||||
};
|
};
|
||||||
})()
|
})()
|
||||||
},
|
},
|
||||||
|
|
|
||||||
53
game.js
53
game.js
|
|
@ -27,6 +27,7 @@ function showLesson(index) {
|
||||||
|
|
||||||
//console.log(isLessonDone(lesson.id));
|
//console.log(isLessonDone(lesson.id));
|
||||||
updateLessonStatus();
|
updateLessonStatus();
|
||||||
|
PopulateObjectives(lesson.objectives); // Populate objectives for the lesson
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadLessonContent(lesson) {
|
function loadLessonContent(lesson) {
|
||||||
|
|
@ -60,6 +61,17 @@ function checkLessonDone() {
|
||||||
if (result.done) {
|
if (result.done) {
|
||||||
markLessonDone(lesson.id);
|
markLessonDone(lesson.id);
|
||||||
}
|
}
|
||||||
|
if (result.progressArray){
|
||||||
|
console.log("Progress: ", result.progressArray);
|
||||||
|
for (let i = 0; i < result.progressArray.length; i++) {
|
||||||
|
const objective = result.progressArray[i];
|
||||||
|
if (objective) {
|
||||||
|
toggleObjective(i, true); // Mark as completed
|
||||||
|
} else {
|
||||||
|
toggleObjective(i, false); // Mark as not completed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (result.hint) {
|
if (result.hint) {
|
||||||
logToConsole("Hint: " + result.hint, false);
|
logToConsole("Hint: " + result.hint, false);
|
||||||
//console.log("Hint:", result.hint); // Or show it in your console UI
|
//console.log("Hint:", result.hint); // Or show it in your console UI
|
||||||
|
|
@ -132,8 +144,47 @@ function clearLessonProgress() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let objectiveElements = []; // store checkbox + item div
|
||||||
|
|
||||||
|
const listContainer = document.getElementById("objectives-list");
|
||||||
|
|
||||||
|
function PopulateObjectives(objectives) {
|
||||||
|
|
||||||
|
listContainer.innerHTML = ""; // Clear the DOM
|
||||||
|
objectiveElements.length = 0; // Clear the stored references
|
||||||
|
objectives.forEach((text, index) => {
|
||||||
|
const item = document.createElement("div");
|
||||||
|
item.className = "objective";
|
||||||
|
|
||||||
|
const checkbox = document.createElement("input");
|
||||||
|
checkbox.type = "checkbox";
|
||||||
|
checkbox.id = "obj-" + index;
|
||||||
|
checkbox.disabled = true; // make it non-interactive
|
||||||
|
|
||||||
|
const label = document.createElement("label");
|
||||||
|
label.htmlFor = checkbox.id;
|
||||||
|
label.textContent = text;
|
||||||
|
|
||||||
|
item.appendChild(checkbox);
|
||||||
|
item.appendChild(label);
|
||||||
|
listContainer.appendChild(item);
|
||||||
|
|
||||||
|
objectiveElements.push({ checkbox, item }); // Store reference
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function toggleObjective(index, completed = true) {
|
||||||
|
const obj = objectiveElements[index];
|
||||||
|
if (obj) {
|
||||||
|
obj.checkbox.checked = completed;
|
||||||
|
obj.item.classList.toggle("completed", completed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clearLessonProgress(); // Clear progress on load for testing
|
clearLessonProgress(); // Clear progress on load for testing
|
||||||
showLesson(7);
|
showLesson(6);
|
||||||
|
|
||||||
const consoleElement = document.getElementById("console");
|
const consoleElement = document.getElementById("console");
|
||||||
const gameCanvas = document.getElementById("gameCanvas");
|
const gameCanvas = document.getElementById("gameCanvas");
|
||||||
|
|
|
||||||
16
index.html
16
index.html
|
|
@ -27,7 +27,10 @@
|
||||||
|
|
||||||
<!-- New Lesson Box / Instructions Area -->
|
<!-- New Lesson Box / Instructions Area -->
|
||||||
<section id="lesson-box">
|
<section id="lesson-box">
|
||||||
<div class="content-width">
|
<div class="content-width" style="display: flex; gap: 20px; align-items: flex-start;">
|
||||||
|
|
||||||
|
<!-- 📘 Lesson content area (3/4 width) -->
|
||||||
|
<div style="flex: 3;">
|
||||||
<h2 id="lesson-title">Lesson Title</h2>
|
<h2 id="lesson-title">Lesson Title</h2>
|
||||||
<p id="lesson-content">Lesson Content</p>
|
<p id="lesson-content">Lesson Content</p>
|
||||||
|
|
||||||
|
|
@ -40,8 +43,17 @@
|
||||||
<button id="next-lesson">Next →</button>
|
<button id="next-lesson">Next →</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
|
||||||
|
|
||||||
|
<!-- ✅ Objectives (1/4 width) -->
|
||||||
|
<aside style="flex: 1;">
|
||||||
|
<h2>Objectives</h2>
|
||||||
|
<div id="objectives-list">
|
||||||
|
<!-- Populated via JavaScript -->
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<!-- Main Content -->
|
<!-- Main Content -->
|
||||||
<main>
|
<main>
|
||||||
|
|
|
||||||
22
style.css
22
style.css
|
|
@ -16,6 +16,28 @@ html {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.objective {
|
||||||
|
margin: 10px 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objective label {
|
||||||
|
margin-left: 8px;
|
||||||
|
transition: color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.completed label {
|
||||||
|
color: green;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
pointer-events: none; /* make it non-clickable */
|
||||||
|
}
|
||||||
|
|
||||||
/* ===== Header (top bar) ===== */
|
/* ===== Header (top bar) ===== */
|
||||||
header {
|
header {
|
||||||
background-color: #f3f4f6;
|
background-color: #f3f4f6;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue