onlinecodesimulator/data/lessons.js

253 lines
8.6 KiB
JavaScript

export const lessons = [
{
id: 'lesson1',
title: '1. Introduction to Python',
difficulty: 'easy',
content: `
<p>Let's learn some Python..</p>
<p>We'll start with what's called a "Hello World" program to make sure everythings working.</p>
<p>In Python, this is done with the <code>print</code> function.</p>
<ol>
<li>In the code editor below, type <code>print("Hello World")</code></li>
<li>Click the "Run" button to execute your code</li>
<li>You should see "Hello World" printed in the output area</li>
</ol>
`,
doneCondition: (consoleText) => consoleText.includes("Hello World")
},
{
id: 'lesson2',
title: 'Data Types and Variables',
difficulty: 'easy',
content: `
<p>Did you try typeing <code>print(Hello World)</code>, without the quotation marks?</p>
<p>If you didn't, give it a try now.</p>
</br>
<p>Thats what we call a <strong>Syntax Error</strong>.</p>
<p>Python doesn't know what the term (Hello World) means, the "" we added before tell Python that this is a "string", a series of characters that it doesn't need to try and understand, just to repeat.</p>
</br>
String is just one of the many <strong>Data Types</strong> that Python has.</p>
To continue, I want you to print the following all at once, each on a new line:
<ol>
<li>String: <code>print("Hello World")</code></li>
<li>Integer: <code>print(42)</code></li>
<li>Float: <code>print(3.14)</code></li>
<li>Boolean: <code>print(True)</code></li>
</ol>
<p>Click the "Run" button to execute your code</p>
`,
doneCondition: (consoleText => {
// Persistent tracking object inside closure
const progress = {
stringDone: false,
intDone: false,
floatDone: false,
boolDone: false,
syntaxErrorDone: false,
};
//const syntaxErrorRegex = /SyntaxError/i;
const stringRegex = /(["'])(?:(?=(\\?))\2.)*?\1/; // optional improvement based on context
const intRegex = /(?<![\d.])[-+]?\d+(?![\d.])/;
const floatRegex = /[-+]?(?:\d+\.\d*|\.\d+)(?:[eE][-+]?\d+)?/;
const boolRegex = /\b(True|False|true|false)\b/;
return (text) => {
// if (!progress.syntaxErrorDone && syntaxErrorRegex.test(text)) {
// progress.syntaxErrorDone = true;
// }
if (!progress.stringDone && stringRegex.test(text)) {
progress.stringDone = true;
}
if (!progress.floatDone && floatRegex.test(text)) {
progress.floatDone = true;
}
if (!progress.intDone && intRegex.test(text)) {
progress.intDone = true;
}
if (!progress.boolDone && boolRegex.test(text)) {
progress.boolDone = true;
}
let missing = [];
//if (!progress.syntaxErrorDone) missing.push("syntax error");
//if (!progress.stringDone) missing.push("string");
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 ";
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',
title: '3. Arithmetic Operations',
difficulty: 'easy',
content: `
<p>Let's get python to do our math homework for us.</p>
<p>Python can handle basic arithmetic operations like addition, subtraction, multiplication, and division.</p>
<p>Try the following operations in the code editor:</p>
<ol>
<li>Addition: <code>print(5 + 3)</code></li>
<li>Subtraction: <code>print(10 - 2)</code></li>
<li>Multiplication: <code>print(4 * 7)</code></li>
<li>Division: <code>print(20 / 5)</code></li>
</ol>
`,
doneCondition: (consoleText => {
// Persistent tracking object inside closure
const progress = {
addDone: false,
subDone: false,
mulDone: false,
divDone: false,
};
return (text) => {
// if (!progress.syntaxErrorDone && syntaxErrorRegex.test(text)) {
// progress.syntaxErrorDone = true;
// }
if (!progress.addDone && text.includes("+")) {
progress.addDone = true;
}
if (!progress.subDone && text.includes("-")) {
progress.subDone = true;
}
if (!progress.mulDone && text.includes("*")) {
progress.mulDone = true;
}
if (!progress.divDone && text.includes("/")) {
progress.divDone = true;
}
let missing = [];
//if (!progress.syntaxErrorDone) missing.push("syntax error");
//if (!progress.stringDone) missing.push("string");
if (!progress.addDone) missing.push("addition");
if (!progress.subDone) missing.push("subtraction");
if (!progress.mulDone) missing.push("multiplication");
if (!progress.divDone) missing.push("division");
let hint = "I still need you to do some ";
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.addDone && progress.subDone && progress.mulDone && progress.divDone;
return { done, hint };
};
})()
},
{
id: 'lesson4',
title: '4. Variables',
difficulty: 'easy',
content: `
<p>It's common for us to need to keep some data or objects over multiple lines, for that we use <strong>variables</strong>.</p>
<p>Think of a variable as a container that holds an object for us to use later.</p>
<p>To make one, we only need to give it a name, and assign it a value.</p>
<p><code>bob = 32</code></p>
<p>In this case, we created a variable called <code>bob</code> and assigned it the value <code>32</code>.</p>
<p>As far as Python is concerned, <code>bob</code> is just a name for the number <code>32</code>.</p>
<p>Lets test it</p>
<ol>
<li>Initialize bob with the value 32: <code>bob = 32</code></li>
<li>Print the value of bob: <code>print(bob)</code></
</ol>
`,
steps: [
{
content: `<p>First, try printing an addition: <code>print(2 + 3)</code></p>`,
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: (code => {
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
}
// 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
}
}
// Build hint
let missing = [];
if (!progress.varCreated) missing.push("create a variable");
if (progress.varCreated && !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 };
};
})()
},
];