Skip to content

Commit

Permalink
Configure math page from index.
Browse files Browse the repository at this point in the history
  • Loading branch information
jerjou committed Aug 5, 2020
1 parent 66ea211 commit 2da0899
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 56 deletions.
95 changes: 89 additions & 6 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="mercury.css" type="text/css">
<title>Document</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="mercury.css" type="text/css">
<style>
input[type=number] {
width: 5rem;
display: inline;
font-weight: bold;
margin:0;
}
label {
display: inline;
}
</style>
<title>Document</title>
</head>
<body>
<ul><h2>Homeschooling "worksheets"</h2>
<li>
<a href="math.html">Addition &amp; Subtraction drills</a>
<br/>
<i>Auto-generated addition and subtraction problems, with configurable limits.</i>
<form action="math.html" method="GET">
<button>Addition &amp; Subtraction drills</button>
<br/>
<i>Auto-generated addition and subtraction problems, with configurable limits.</i>
<br/>
<label>Generate <input type=number min=1 name=n value=10 /></label> problems, with a
<label>minimum sum of <input type=number name=min value=0 /></label> and a
<label>maximum sum of <input type=number name=max value=10 /></label>, and
<label><input type=number name=setSize value=2 /> numbers per problem</label>.
There should be
<label><input type=number min=0 name=sum_parts value=1 /> addition problem</label> for every
<label><input type=number min=0 name=difference_parts value=1 /> subtraction problem</label>.
</form>
</li>
<li>
<a href="words.html">Word reading drills</a>
Expand All @@ -19,5 +41,66 @@
recognizing useful words by sight.</i>
</li>
</ul>

<ul><h2>Simulation</h2>
</ul>

<ul>Errata
<li>This is what we teach our kids</li>
<ul>
<li>Reading: <a href="https://archive.org/details/teachyourchildto0000enge">Teach Your Child
to Read in 100 Easy Lessons</a></li>
<ul>Good childrens' books
<li><i>Fraidy Zoo</i> and <i>How do you Dance?</i></li>
<li><i>Leslie Patricelli</i></li>
</ul>

<li><ul>Math
<li>Counting by 2's</li>
</ul></li>

<li><ul>Engineering
<li><a href="https://www.youtube.com/channel/UCWBkudOTaVbvkCBc0pyZFMA">How it's made</a></li>
<li><a href="https://www.youtube.com/user/destinws2">Smarter Every Day</a></li>
</ul></li>

<li>Geography: <a href="https://maps.google.com">Google Maps / Earth</a></li>

<li><ul>PE:
<li>Riding a bike - balance bike, training wheels, take off training wheels</li>
<li>Swimming - puddle jumpers</li>
<li>Tennis</li>
</ul></li>

<li><ul>Music
</ul></li>

<li><ul>Art: <a href="https://www.youtube.com/user/ArtforKidsHub">ArtForKidsHub</a>
</ul></li>

<li><ul>
<li><b>2020-07-19:</b> Count by 2's, Soccer</li>
</ul></li>
</ul>
</ul>

<ul><h2>TODO</h2>
<li><i>TODO</i> fractions, ratios</li>
<li><i>TODO</i> angles - radians, ratios, fractions</li>
<li><i>TODO</i> shapes / geometry</li>

<li><i>TODO</i> how suction works (ie equalized pressure makes no movement, unbalanced pressure
creates suction)</li>
<li><i>TODO</i> why hot air rises (density)</li>
<li><i>TODO</i> water level dropping due to evaporation at room temperature</li>
<li><i>TODO</i> phase changes - ie starting with ice and slowly increasing temperature until you
get water, then keep increasing temperature until you get steam</li>
<li><i>TODO</i> temperature conduction - how heat and cold are transferred eg when you touch
something hot or cold.</li>
<li><i>TODO</i> <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations">movable clock</a> to show how minute hand is related to hour hand is related to
second hand. button to reveal time in digital format. maybe a number line to show minutes in
an hour - why halfway around is 30 / 60</li>
</ul>

</body>
</html>
30 changes: 29 additions & 1 deletion math.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
body, input {
body {
font-size: 3rem;
}

form.controls {
position: absolute;
top:0;right:0;
border: 1px solid rgba(0,0,0,.5);
font-size: 1rem;
display: flex;
flex-direction: column;
display: none;
}
form.controls label {
display: flex;
flex-direction: row;
justify-content: end;
}
form.controls input {
font-size: 1rem;
margin-left: .5rem;
}

form.problem {
display: flex;
flex-direction: row;
Expand All @@ -13,6 +33,9 @@ form.problem label {
padding: .9rem 1rem;
position: relative;
}
form.problem input {
font-size: inherit;
}
form>input[type=submit] {
display: none;
}
Expand Down Expand Up @@ -64,3 +87,8 @@ label.wrong input {
label.right input {
border-color: green;
}

button.regenerate {
float: right;
padding: .5rem 1rem;
}
1 change: 1 addition & 0 deletions math.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<html>
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="https://unpkg.com/@coreui/icons/css/free.min.css">
<link rel="stylesheet" href="math.css">
<script src="math.js"></script>
Expand Down
138 changes: 89 additions & 49 deletions math.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,75 +7,88 @@ let $el = (tag, props) => {
}
return el;
};
Array.prototype.slideBy = function(windo) {
let end = 1 + this.length - windo;
return [...Array(end).keys()].map(i => this.slice(i, i + windo));
};
let rint = (max) => Math.floor(max * Math.random());
let numDigits = (n) => Math.log10(n) + 1 | 0;
let makeSum = (min, max) => {
let range = max - min;
let [num1, num2] = [min + rint(range), min + rint(range)];
let [sum, first] = num1 > num2 ? [num1, num2] : [num2, num1];

let second = sum - first;
return [sum, first, second];
// Generates a set of random numbers that sum to the first element of the
// returned array
let makeSum = (min, max, n=2) => {
let range = max - min;
let divisions = [...Array(n).keys()].map(_ => min + rint(range));
divisions.sort((a, b) => a - b);
console.log(divisions);
let nums = [
divisions[0], ...divisions.slideBy(2).map(([a, b]) => b - a)];
let sum = divisions.pop();
return [sum, ...nums];
};
var qs = {
getI: (k) => {
getI: (k, def) => {
qs.parsed = new URLSearchParams(location.search);
qs.getI = (k) => parseInt(qs.parsed.get(k), 10);
return qs.getI(k);
qs.getI = (k, def) => {
let r = parseInt(qs.parsed.get(k), 10);
return isNaN(r) ? def : r;
};
return qs.getI(k, def);
},
getF: (k) => {
qs.parsed = new URLSearchParams(location.search);
qs.getF = (k) => parseFloat(qs.parsed.get(k), 10);
return qs.getF(k);
}
}
addEventListener('DOMContentLoaded', () => {
let container = $('.math');
let numProbs = qs.getI('n') || 8;
let min = qs.getI('min') || 0;
let max = qs.getI('max') || 11;
let style = $el('style');
$('head').appendChild(style);
style.sheet.insertRule(`label>input{width:${2 * numDigits(max)}rem}`);
let form = $el('form', {className: 'problem'});
let checkInput = (input) => {
let label = input.closest('label');
if (!input.value.length) {
label.classList.remove('right');
label.classList.remove('wrong');
return;

function checkInput(input) {
let label = input.closest('label');
if (!input.value.length) {
label.classList.remove('right');
label.classList.remove('wrong');
return;
}
if (parseInt(input.value, 10) === input.solution) {
if (!label.classList.replace('wrong', 'right')) {
label.classList.add('right');
}
if (parseInt(input.value, 10) === input.solution) {
if (!label.classList.replace('wrong', 'right')) {
label.classList.add('right');
}
} else {
if (!label.classList.replace('right', 'wrong')) {
label.classList.add('wrong');
}
setTimeout(() => input.select(), 10);
let nextProblem = label.nextSibling;
if (!nextProblem || nextProblem.classList.contains('right') || !nextProblem.matches('label')) {
nextProblem = label.parentNode.querySelector('label:not(.right)');
}
};
let checkAnswers = (e) => {
e.preventDefault();
if (e.target.tagName === 'INPUT') {
checkInput(e.target);
} else {
[...form.querySelectorAll('input[type=text]')].forEach(checkInput);
if (nextProblem) {
setTimeout(_ => nextProblem.querySelector('input').select(), 10);
}
} else {
if (!label.classList.replace('right', 'wrong')) {
label.classList.add('wrong');
}
};
setTimeout(() => input.select(), 10);
}
}

function checkAnswers(e) {
e.preventDefault();
if (e.target.tagName === 'INPUT') {
checkInput(e.target);
} else {
[...$('form').querySelectorAll('input[type=text]')].forEach(checkInput);
}
}

function generateProblems(numProbs, min, max, mix) {
let form = $el('form', {className: 'problem'});

let mix = qs.getF('mix');
mix = isNaN(mix) ? .5 : mix;
for (let i = 0; i < numProbs; i++) {
let sum = makeSum(min, max);
let sum = makeSum(min, max, qs.getI('setSize', 2));
let equation;
if (Math.random() < mix) {
equation = $el('label', {innerHTML: `${sum[1]} + ${sum[2]} =`});
equation = $el('label', {innerHTML: `${sum.slice(1).join(' + ')} =`});
equation.appendChild($el('input', {solution: sum[0], type:'text'}));
} else {
equation = $el('label', {innerHTML: `${sum[0]} &#x2212; ${sum[1]} =`});
equation.appendChild($el('input', {solution: sum[2], type:'text'}));
equation = $el('label', {innerHTML: `${sum.slice(0, -1).join(' &#x2212; ')} =`});
equation.appendChild($el('input', {solution: sum[sum.length-1], type:'text'}));
}
// Icons for right and wrong
equation.appendChild($el('i', {className: 'cil-check right'}));
Expand All @@ -89,9 +102,36 @@ addEventListener('DOMContentLoaded', () => {
input.addEventListener('blur', () => input.closest('label').classList.remove('active'));
});

container.appendChild(form);
form.querySelector('input').focus();
form.appendChild($el('input', {type: 'submit'}));
form.addEventListener('submit', checkAnswers);

setTimeout(_ => form.querySelector('input').focus(), 10);

return form;
}
addEventListener('DOMContentLoaded', _ => {
let container = $('.math');
let numProbs = qs.getI('n', 8);
let min = qs.getI('min', 0);
let max = qs.getI('max', 11);
let sum_parts = qs.getI('sum_parts', 1);
let difference_parts = qs.getI('difference_parts', 1);
let mix = sum_parts / (sum_parts + difference_parts);

let style = $el('style');
$('head').appendChild(style);
style.sheet.insertRule(`label>input{width:${2 * numDigits(max)}rem}`);

let form = generateProblems(numProbs, min, max, mix);
container.appendChild(form);

let regenerate = $el('button', {className: 'regenerate', innerText: 'Regenerate'});
regenerate.addEventListener('click', e => {
e.preventDefault();
let form = generateProblems(numProbs, min, max, mix);
container.replaceChild(form, container.childNodes[0]);
});
container.appendChild(regenerate);

});

0 comments on commit 2da0899

Please sign in to comment.