Download script.js from ParulPandey/Multiplication_Farm_Fun: direct link, hf CLI and curl.
- Browser
- Download file 9.57 kB
-
https://huggingface.co/spaces/ParulPandey/Multiplication_Farm_Fun/resolve/main/script.js
- Command line
-
hf download hf://spaces/ParulPandey/Multiplication_Farm_Fun/script.js
-
curl -L -o script.js https://huggingface.co/spaces/ParulPandey/Multiplication_Farm_Fun/resolve/main/script.js
9.57 kB
| 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; // Number of plot choices (1 correct, 2 incorrect) | |
| const MAX_FACTOR = 6; // Maximum number for factors (e.g., up to 6x6) | |
| const TOTAL_ROUNDS = 10; // Number of questions in a game | |
| // --- Items for the Farm --- | |
| const farmItems = ['🍎', '🥕', '🐔', '🐑', '🌻', '🌽']; | |
| // --- Generate Multiplication Problems --- | |
| let possibleProblems = []; | |
| function generateProblems() { | |
| possibleProblems = []; | |
| for (let i = 1; i <= MAX_FACTOR; i++) { | |
| // Start j from 1 to include squares and both orders (e.g., 2x3 and 3x2 are distinct visual arrays) | |
| for (let j = 1; j <= MAX_FACTOR; j++) { | |
| possibleProblems.push({ num1: i, num2: j, answer: i * j }); | |
| } | |
| } | |
| // Remove duplicates might be needed if we consider A*B same as B*A later | |
| } | |
| // --- Game State --- | |
| let score = 0; | |
| let currentProblem = null; | |
| let currentRound = 0; | |
| let waitingForNext = false; | |
| // --- Utility: Get Random Int --- | |
| function getRandomInt(max) { | |
| return Math.floor(Math.random() * max); | |
| } | |
| // --- Utility: Shuffle Array --- | |
| 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]]; | |
| } | |
| } | |
| // --- Setup a New Round --- | |
| 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++; | |
| // 1. Choose a target problem | |
| if (!possibleProblems || possibleProblems.length === 0) generateProblems(); // Regenerate if empty | |
| const problemIndex = getRandomInt(possibleProblems.length); | |
| currentProblem = possibleProblems.splice(problemIndex, 1)[0]; // Pick and remove | |
| num1Display.textContent = currentProblem.num1; | |
| num2Display.textContent = currentProblem.num2; | |
| // 2. Create options array (as {rows, cols}) | |
| // Allow commutative property visually (3x4 can be 3 rows of 4 OR 4 rows of 3) | |
| const correctOption = { rows: currentProblem.num1, cols: currentProblem.num2 }; | |
| const options = [correctOption]; | |
| // 3. Generate incorrect options | |
| while (options.length < OPTIONS_COUNT) { | |
| let wrongRows, wrongCols; | |
| let isDuplicate = true; | |
| let attempts = 0; // Prevent infinite loop | |
| while(isDuplicate && attempts < 20) { | |
| // Generate wrong dimensions, make sure at least one is different | |
| const changeRows = Math.random() > 0.5; | |
| wrongRows = changeRows ? getRandomInt(MAX_FACTOR) + 1 : correctOption.rows; | |
| wrongCols = !changeRows ? getRandomInt(MAX_FACTOR) + 1 : correctOption.cols; | |
| // Ensure it's actually wrong AND not zero product AND different from target | |
| if((wrongRows !== correctOption.rows || wrongCols !== correctOption.cols) && | |
| (wrongRows * wrongCols > 0) ) { | |
| // Check if this combination (or its commutative pair) is already in options | |
| isDuplicate = options.some(opt => | |
| (opt.rows === wrongRows && opt.cols === wrongCols) || | |
| (opt.rows === wrongCols && opt.cols === wrongRows) | |
| ); | |
| } else { | |
| isDuplicate = true; // Force retry if generated same as correct or zero product | |
| } | |
| attempts++; | |
| } | |
| // If stuck finding unique, just create a simple wrong one | |
| 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) | |
| ); // Final check | |
| } | |
| if (!isDuplicate) { | |
| options.push({ rows: wrongRows, cols: wrongCols }); | |
| } | |
| } | |
| // 4. Shuffle options | |
| shuffleArray(options); | |
| // 5. Create and display field elements | |
| options.forEach(plot => { | |
| const fieldDiv = document.createElement('div'); | |
| fieldDiv.classList.add('field-option'); | |
| fieldDiv.dataset.rows = plot.rows; | |
| fieldDiv.dataset.cols = plot.cols; | |
| // Style the grid layout for items *inside* this field | |
| fieldDiv.style.gridTemplateColumns = `repeat(${plot.cols}, auto)`; // auto size columns | |
| fieldDiv.style.gridTemplateRows = `repeat(${plot.rows}, auto)`; // auto size rows | |
| // Set a max-width to prevent huge single rows/columns | |
| fieldDiv.style.maxWidth = `${plot.cols * 35}px`; // Approx item size + gap | |
| // Add items (emoji) | |
| 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); | |
| } | |
| // --- Handle Field Choice Click --- | |
| function handleChoiceClick(event) { | |
| if (waitingForNext) return; | |
| const clickedField = event.currentTarget; | |
| const clickedRows = parseInt(clickedField.dataset.rows); | |
| const clickedCols = parseInt(clickedField.dataset.cols); | |
| waitingForNext = true; | |
| // Remove listeners | |
| document.querySelectorAll('.field-option').forEach(opt => { | |
| const clone = opt.cloneNode(true); | |
| opt.parentNode.replaceChild(clone, opt); | |
| }); | |
| // Check if correct (allow commutative: A x B or B x A) | |
| 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'); | |
| // Highlight the correct answer(s) | |
| setTimeout(() => { | |
| const correctElement1 = fieldChoicesContainer.querySelector(`.field-option[data-rows="${currentProblem.num1}"][data-cols="${currentProblem.num2}"]`); | |
| if (correctElement1) correctElement1.classList.add('correct-choice'); | |
| // Also highlight commutative pair if it exists and is different | |
| const correctElement2 = fieldChoicesContainer.querySelector(`.field-option[data-rows="${currentProblem.num2}"][data-cols="${currentProblem.num1}"]`); | |
| if (correctElement2 && correctElement1 !== correctElement2) correctElement2.classList.add('correct-choice'); | |
| }, 300); | |
| } | |
| // Load next round | |
| setTimeout(setupNewRound, 2500); // Longer delay to see feedback/answer | |
| } | |
| // --- End Game --- | |
| function endGame() { | |
| feedbackArea.textContent = `Game Over! Your final score: ${score} / ${TOTAL_ROUNDS}! Great work! 🥳`; | |
| feedbackArea.className = 'correct-feedback'; // Use correct style for positive end | |
| fieldChoicesContainer.innerHTML = '<p style="font-size:1.2em; color: #795548;">Refresh the page to play again!</p>'; // Clear options | |
| // Optionally disable further interaction if needed | |
| } | |
| // --- Initial Game Start --- | |
| totalQuestionsDisplay.textContent = TOTAL_ROUNDS; // Set total rounds display | |
| generateProblems(); // Create the initial list of problems | |
| setupNewRound(); | |
| }); // End DOMContentLoaded |