JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
HTML
<div id="timer"></div>
<canvas id="canvas"></canvas>
<p><b style="color: red">Prototype!</b> Click on the canvas to place a point. Try to find the absolute minimum of the invisible function as quickly as possible!</p>
CSS
#timer {
color: red;
}
JavaScript
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
canvas.width = 640;
canvas.height = 480;
const timer = document.querySelector("#timer");
let timerStart = NaN;
let timerRunning = false;
function startTimer() {
timerStart = Date.now();
timerRunning = true;
updateTimer();
}
function updateTimer() {
if (timerRunning) {
requestAnimationFrame(updateTimer);
}
const s = Math.round((Date.now() - timerStart) || 0) / 1000;
timer.innerText = s;
}
function stopTimer() {
timerRunning = false;
}
/*
const polynomial = [0, -2, 0.3, 0.5, 0.065];
function f(x) {
const sum = (values) => values.reduce((a, b) => a + b, 0);
return sum(polynomial.map((term, n) => term * x ** n));
}
*/
const functions = [
x => 0.005 * (x + 7) * (x + 1) * (x - 5)**2,
x => 0.0002 * (x+7) * (x+6) * (x+1) * (x-2) * (x-4) * (x-8)
];
const f = functions[Math.floor(Math.random() * functions.length)];
function fPrime(x) {
return (f(x + 0.01) - f(x - 0.01)) / 0.02;
}
function range(start, end, step) {
let result = [];
for (let x = start; x <= end; x += step) {
result.push(x);
}
return result;
}
const minValue = Math.min(...range(-8, 8, 0.001).map(f))
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
canvas.addEventListener("click", function (event) {
if (!timerRunning) {
startTimer();
}
const mouseX = event.clientX;
const canvasX = event.target.getBoundingClientRect().left;
const scale = 40;
const x = ((mouseX - canvasX) - canvas.width / 2) / scale;
const y = f(x);
const yPrime = fPrime(x);
const win = y < minValue + 0.01;
if (win) {
stopTimer();
}
ctx.strokeStyle = "#333";
ctx.beginPath();
ctx.moveTo(canvas.width / 2 + x * scale, 0);
ctx.lineTo(canvas.width / 2 + x * scale, canvas.height);
ctx.stroke();
ctx.strokeStyle = "#ddd";
ctx.beginPath();
ctx.moveTo(
canvas.width / 2 + (x - 0.5) * scale,
canvas.height / 2 - (y - 0.5 * yPrime) *...