|
document.addEventListener('DOMContentLoaded', () => { |
|
const scoreDisplay = document.getElementById('score'); |
|
const numeratorDisplay = document.querySelector('#fraction-order .numerator'); |
|
const denominatorDisplay = document.querySelector('#fraction-order .denominator'); |
|
const feedbackArea = document.getElementById('feedback-area'); |
|
const pizzaChoicesContainer = document.getElementById('pizza-choices'); |
|
|
|
const PIZZA_SIZE = 140; |
|
const OPTIONS_COUNT = 3; |
|
|
|
|
|
|
|
const possibleFractions = [ |
|
|
|
{ num: 1, den: 2 }, |
|
|
|
{ num: 1, den: 3 }, { num: 2, den: 3 }, |
|
|
|
{ num: 1, den: 4 }, { num: 2, den: 4 }, { num: 3, den: 4 }, |
|
|
|
{ num: 1, den: 6 }, { num: 2, den: 6 }, { num: 3, den: 6 }, { num: 4, den: 6 }, { num: 5, den: 6 }, |
|
|
|
{ num: 1, den: 8 }, { num: 2, den: 8 }, { num: 3, den: 8 }, { num: 4, den: 8 }, |
|
{ num: 5, den: 8 }, { num: 6, den: 8 }, { num: 7, den: 8 }, |
|
]; |
|
|
|
|
|
let score = 0; |
|
let currentOrder = null; |
|
let waitingForNext = false; |
|
|
|
|
|
function getRandomInt(max) { |
|
return Math.floor(Math.random() * max); |
|
} |
|
|
|
|
|
function shuffleArray(array) { |
|
for (let i = array.length - 1; i > 0; i--) { |
|
const j = getRandomInt(i + 1); |
|
[array[i], array[j]] = [array[j], array[i]]; |
|
} |
|
} |
|
|
|
|
|
function drawPizza(canvas, num, den) { |
|
const ctx = canvas.getContext('2d'); |
|
const radius = canvas.width / 2; |
|
const centerX = radius; |
|
const centerY = radius; |
|
const sliceAngle = (Math.PI * 2) / den; |
|
|
|
|
|
const crustColor = '#f4a460'; |
|
const sauceColor = '#ff6347'; |
|
const cheeseColor = '#fffacd'; |
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height); |
|
|
|
|
|
ctx.fillStyle = crustColor; |
|
ctx.beginPath(); |
|
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2); |
|
ctx.fill(); |
|
|
|
|
|
ctx.fillStyle = cheeseColor; |
|
ctx.beginPath(); |
|
ctx.arc(centerX, centerY, radius * 0.95, 0, Math.PI * 2); |
|
ctx.fill(); |
|
|
|
|
|
|
|
ctx.fillStyle = sauceColor; |
|
for (let i = 0; i < num; i++) { |
|
const startAngle = i * sliceAngle - Math.PI / 2; |
|
const endAngle = (i + 1) * sliceAngle - Math.PI / 2; |
|
|
|
ctx.beginPath(); |
|
ctx.moveTo(centerX, centerY); |
|
ctx.arc(centerX, centerY, radius * 0.95, startAngle, endAngle); |
|
ctx.closePath(); |
|
ctx.fill(); |
|
} |
|
|
|
|
|
ctx.strokeStyle = crustColor; |
|
ctx.lineWidth = 2; |
|
for (let i = 0; i < den; i++) { |
|
const angle = i * sliceAngle - Math.PI / 2; |
|
ctx.beginPath(); |
|
ctx.moveTo(centerX, centerY); |
|
ctx.lineTo(centerX + radius * 0.95 * Math.cos(angle), centerY + radius * 0.95 * Math.sin(angle)); |
|
ctx.stroke(); |
|
} |
|
} |
|
|
|
|
|
|
|
function setupNewRound() { |
|
waitingForNext = false; |
|
pizzaChoicesContainer.innerHTML = ''; |
|
feedbackArea.textContent = "Click the pizza that matches the order!"; |
|
feedbackArea.className = ''; |
|
|
|
|
|
currentOrder = possibleFractions[getRandomInt(possibleFractions.length)]; |
|
numeratorDisplay.textContent = currentOrder.num; |
|
denominatorDisplay.textContent = currentOrder.den; |
|
|
|
|
|
const options = [{ num: currentOrder.num, den: currentOrder.den }]; |
|
|
|
|
|
while (options.length < OPTIONS_COUNT) { |
|
const randomFraction = possibleFractions[getRandomInt(possibleFractions.length)]; |
|
|
|
const isDuplicate = options.some(opt => opt.num === randomFraction.num && opt.den === randomFraction.den); |
|
if (!isDuplicate) { |
|
options.push(randomFraction); |
|
} |
|
|
|
if(options.length < OPTIONS_COUNT && possibleFractions.length <= options.length){ |
|
console.warn("Not enough unique fractions to generate distractors. Reusing."); |
|
|
|
let foundNew = false; |
|
for(let frac of possibleFractions){ |
|
if(!options.some(opt => opt.num === frac.num && opt.den === frac.den)){ |
|
options.push(frac); |
|
foundNew = true; |
|
break; |
|
} |
|
} |
|
if(!foundNew && options.length < OPTIONS_COUNT) options.push(randomFraction); |
|
} |
|
|
|
} |
|
|
|
|
|
shuffleArray(options); |
|
|
|
|
|
options.forEach(fraction => { |
|
const optionDiv = document.createElement('div'); |
|
optionDiv.classList.add('pizza-option'); |
|
optionDiv.dataset.num = fraction.num; |
|
optionDiv.dataset.den = fraction.den; |
|
|
|
const canvas = document.createElement('canvas'); |
|
canvas.classList.add('pizza-canvas'); |
|
canvas.width = PIZZA_SIZE; |
|
canvas.height = PIZZA_SIZE; |
|
|
|
optionDiv.appendChild(canvas); |
|
pizzaChoicesContainer.appendChild(optionDiv); |
|
|
|
drawPizza(canvas, fraction.num, fraction.den); |
|
|
|
optionDiv.addEventListener('click', handleChoiceClick); |
|
}); |
|
|
|
console.log("New round setup. Target:", currentOrder); |
|
} |
|
|
|
|
|
function handleChoiceClick(event) { |
|
if (waitingForNext) return; |
|
|
|
const clickedPizza = event.currentTarget; |
|
const clickedNum = parseInt(clickedPizza.dataset.num); |
|
const clickedDen = parseInt(clickedPizza.dataset.den); |
|
|
|
waitingForNext = true; |
|
|
|
|
|
document.querySelectorAll('.pizza-option').forEach(opt => { |
|
|
|
const clone = opt.cloneNode(true); |
|
opt.parentNode.replaceChild(clone, opt); |
|
}); |
|
|
|
|
|
|
|
if (clickedNum === currentOrder.num && clickedDen === currentOrder.den) { |
|
|
|
score++; |
|
scoreDisplay.textContent = score; |
|
feedbackArea.textContent = `Yummy! That's ${currentOrder.num}/${currentOrder.den}! π`; |
|
feedbackArea.className = 'correct-feedback'; |
|
clickedPizza.classList.add('correct-choice'); |
|
|
|
|
|
const newClickedElement = pizzaChoicesContainer.querySelector(`.pizza-option[data-num="${clickedNum}"][data-den="${clickedDen}"]`); |
|
if (newClickedElement) newClickedElement.classList.add('correct-choice'); |
|
|
|
|
|
} else { |
|
|
|
feedbackArea.textContent = `Oops! That shows ${clickedNum}/${clickedDen}. Try the next one! π€`; |
|
feedbackArea.className = 'incorrect-feedback'; |
|
|
|
|
|
const newClickedElement = pizzaChoicesContainer.querySelector(`.pizza-option[data-num="${clickedNum}"][data-den="${clickedDen}"]`); |
|
if (newClickedElement) newClickedElement.classList.add('incorrect-choice'); |
|
|
|
|
|
setTimeout(() => { |
|
const correctElement = pizzaChoicesContainer.querySelector(`.pizza-option[data-num="${currentOrder.num}"][data-den="${currentOrder.den}"]`); |
|
if (correctElement) correctElement.classList.add('correct-choice'); |
|
}, 300); |
|
|
|
} |
|
|
|
|
|
setTimeout(setupNewRound, 2000); |
|
} |
|
|
|
|
|
setupNewRound(); |
|
|
|
}); |