|
document.addEventListener('DOMContentLoaded', () => { |
|
const scoreDisplay = document.getElementById('score'); |
|
const totalQuestionsDisplay = document.getElementById('total-questions'); |
|
const num1Display = document.getElementById('num1'); |
|
const num2Display = document.getElementById('num2'); |
|
const feedbackArea = document.getElementById('feedback-area'); |
|
const fieldChoicesContainer = document.getElementById('field-choices'); |
|
|
|
const OPTIONS_COUNT = 3; |
|
const MAX_FACTOR = 6; |
|
const TOTAL_ROUNDS = 10; |
|
|
|
|
|
const farmItems = ['π', 'π₯', 'π', 'π', 'π»', 'π½']; |
|
|
|
|
|
let possibleProblems = []; |
|
function generateProblems() { |
|
possibleProblems = []; |
|
for (let i = 1; i <= MAX_FACTOR; i++) { |
|
|
|
for (let j = 1; j <= MAX_FACTOR; j++) { |
|
possibleProblems.push({ num1: i, num2: j, answer: i * j }); |
|
} |
|
} |
|
|
|
} |
|
|
|
|
|
let score = 0; |
|
let currentProblem = null; |
|
let currentRound = 0; |
|
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 setupNewRound() { |
|
if (currentRound >= TOTAL_ROUNDS) { |
|
endGame(); |
|
return; |
|
} |
|
|
|
waitingForNext = false; |
|
fieldChoicesContainer.innerHTML = ''; |
|
feedbackArea.textContent = "Click the farm plot that matches the problem!"; |
|
feedbackArea.className = ''; |
|
|
|
currentRound++; |
|
|
|
|
|
if (!possibleProblems || possibleProblems.length === 0) generateProblems(); |
|
const problemIndex = getRandomInt(possibleProblems.length); |
|
currentProblem = possibleProblems.splice(problemIndex, 1)[0]; |
|
|
|
num1Display.textContent = currentProblem.num1; |
|
num2Display.textContent = currentProblem.num2; |
|
|
|
|
|
|
|
const correctOption = { rows: currentProblem.num1, cols: currentProblem.num2 }; |
|
const options = [correctOption]; |
|
|
|
|
|
while (options.length < OPTIONS_COUNT) { |
|
let wrongRows, wrongCols; |
|
let isDuplicate = true; |
|
let attempts = 0; |
|
|
|
while(isDuplicate && attempts < 20) { |
|
|
|
const changeRows = Math.random() > 0.5; |
|
wrongRows = changeRows ? getRandomInt(MAX_FACTOR) + 1 : correctOption.rows; |
|
wrongCols = !changeRows ? getRandomInt(MAX_FACTOR) + 1 : correctOption.cols; |
|
|
|
|
|
if((wrongRows !== correctOption.rows || wrongCols !== correctOption.cols) && |
|
(wrongRows * wrongCols > 0) ) { |
|
|
|
|
|
isDuplicate = options.some(opt => |
|
(opt.rows === wrongRows && opt.cols === wrongCols) || |
|
(opt.rows === wrongCols && opt.cols === wrongRows) |
|
); |
|
} else { |
|
isDuplicate = true; |
|
} |
|
attempts++; |
|
} |
|
|
|
if (attempts >= 20) { |
|
wrongRows = correctOption.rows === 1 ? 2 : correctOption.rows -1; |
|
wrongCols = correctOption.cols; |
|
isDuplicate = options.some(opt => |
|
(opt.rows === wrongRows && opt.cols === wrongCols) || |
|
(opt.rows === wrongCols && opt.cols === wrongRows) |
|
); |
|
} |
|
|
|
|
|
if (!isDuplicate) { |
|
options.push({ rows: wrongRows, cols: wrongCols }); |
|
} |
|
} |
|
|
|
|
|
shuffleArray(options); |
|
|
|
|
|
options.forEach(plot => { |
|
const fieldDiv = document.createElement('div'); |
|
fieldDiv.classList.add('field-option'); |
|
fieldDiv.dataset.rows = plot.rows; |
|
fieldDiv.dataset.cols = plot.cols; |
|
|
|
|
|
fieldDiv.style.gridTemplateColumns = `repeat(${plot.cols}, auto)`; |
|
fieldDiv.style.gridTemplateRows = `repeat(${plot.rows}, auto)`; |
|
|
|
fieldDiv.style.maxWidth = `${plot.cols * 35}px`; |
|
|
|
|
|
|
|
const itemEmoji = farmItems[getRandomInt(farmItems.length)]; |
|
for (let i = 0; i < plot.rows * plot.cols; i++) { |
|
const itemSpan = document.createElement('span'); |
|
itemSpan.classList.add('item'); |
|
itemSpan.textContent = itemEmoji; |
|
fieldDiv.appendChild(itemSpan); |
|
} |
|
|
|
fieldDiv.addEventListener('click', handleChoiceClick); |
|
fieldChoicesContainer.appendChild(fieldDiv); |
|
}); |
|
|
|
console.log("New round setup. Target:", currentProblem); |
|
} |
|
|
|
|
|
function handleChoiceClick(event) { |
|
if (waitingForNext) return; |
|
|
|
const clickedField = event.currentTarget; |
|
const clickedRows = parseInt(clickedField.dataset.rows); |
|
const clickedCols = parseInt(clickedField.dataset.cols); |
|
|
|
waitingForNext = true; |
|
|
|
|
|
document.querySelectorAll('.field-option').forEach(opt => { |
|
const clone = opt.cloneNode(true); |
|
opt.parentNode.replaceChild(clone, opt); |
|
}); |
|
|
|
|
|
const isCorrect = (clickedRows === currentProblem.num1 && clickedCols === currentProblem.num2) || |
|
(clickedRows === currentProblem.num2 && clickedCols === currentProblem.num1); |
|
|
|
if (isCorrect) { |
|
score++; |
|
scoreDisplay.textContent = score; |
|
feedbackArea.textContent = `Yes! ${currentProblem.num1} x ${currentProblem.num2} = ${currentProblem.answer}! π`; |
|
feedbackArea.className = 'correct-feedback'; |
|
|
|
const newClickedElement = fieldChoicesContainer.querySelector(`.field-option[data-rows="${clickedRows}"][data-cols="${clickedCols}"]`); |
|
if (newClickedElement) newClickedElement.classList.add('correct-choice'); |
|
|
|
} else { |
|
feedbackArea.textContent = `Oops! That shows ${clickedRows} x ${clickedCols}. The answer was ${currentProblem.answer}. π€`; |
|
feedbackArea.className = 'incorrect-feedback'; |
|
|
|
const newClickedElement = fieldChoicesContainer.querySelector(`.field-option[data-rows="${clickedRows}"][data-cols="${clickedCols}"]`); |
|
if (newClickedElement) newClickedElement.classList.add('incorrect-choice'); |
|
|
|
|
|
setTimeout(() => { |
|
const correctElement1 = fieldChoicesContainer.querySelector(`.field-option[data-rows="${currentProblem.num1}"][data-cols="${currentProblem.num2}"]`); |
|
if (correctElement1) correctElement1.classList.add('correct-choice'); |
|
|
|
const correctElement2 = fieldChoicesContainer.querySelector(`.field-option[data-rows="${currentProblem.num2}"][data-cols="${currentProblem.num1}"]`); |
|
if (correctElement2 && correctElement1 !== correctElement2) correctElement2.classList.add('correct-choice'); |
|
}, 300); |
|
} |
|
|
|
|
|
setTimeout(setupNewRound, 2500); |
|
} |
|
|
|
|
|
function endGame() { |
|
feedbackArea.textContent = `Game Over! Your final score: ${score} / ${TOTAL_ROUNDS}! Great work! π₯³`; |
|
feedbackArea.className = 'correct-feedback'; |
|
fieldChoicesContainer.innerHTML = '<p style="font-size:1.2em; color: #795548;">Refresh the page to play again!</p>'; |
|
|
|
} |
|
|
|
|
|
totalQuestionsDisplay.textContent = TOTAL_ROUNDS; |
|
generateProblems(); |
|
setupNewRound(); |
|
|
|
}); |