Last active
July 22, 2025 02:39
-
-
Save CarterT27/54759dae04dc42297eb025cc520f37c4 to your computer and use it in GitHub Desktop.
Zetamac Score Tracker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Zetamac Score Submitter | |
| // @namespace http://tampermonkey.net/ | |
| // @version 1.1 | |
| // @description Automatically submits your Zetamac arithmetic score to a Google Form. | |
| // @author Carter (with help from Gemini) | |
| // @match *://arithmetic.zetamac.com/* | |
| // @grant GM.xmlHttpRequest | |
| // @connect docs.google.com | |
| // ==/UserScript== | |
| /* | |
| --- HOW TO CONFIGURE FOR YOUR OWN GOOGLE FORM --- | |
| 1. GET THE FORM RESPONSE URL: | |
| - Open your Google Form. | |
| - Click the "Send" button in the top-right corner. | |
| - Go to the "Link" tab (the one with the chain icon). | |
| - Copy the provided link. It will look something like this: | |
| https://docs.google.com/forms/d/e/SOME_LONG_ID/viewform?usp=sf_link | |
| - Take that URL and replace "/viewform?usp=sf_link" with "/formResponse". | |
| - The final URL will be your GOOGLE_FORM_URL. For example: | |
| https://docs.google.com/forms/d/e/SOME_LONG_ID/formResponse | |
| 2. GET THE ENTRY ID FOR THE SCORE QUESTION: | |
| - Open the live version of your form (the one people fill out). | |
| - Right-click on the input box where you would type the score. | |
| - Select "Inspect" or "Inspect Element" from the context menu. | |
| - The developer tools will open. Look for the highlighted `<input>` tag. | |
| - Find the 'name' attribute inside that tag. It will look like: | |
| name="entry.1234567890" | |
| - Copy that entire value (e.g., "entry.1234567890"). This is your SCORE_ENTRY_ID. | |
| 3. UPDATE THE CONFIGURATION BELOW. | |
| */ | |
| (function() { | |
| 'use strict'; | |
| // --- Configuration --- | |
| const GOOGLE_FORM_URL = 'https://docs.google.com/forms/d/e/{FORM_ID}/formResponse'; | |
| const SCORE_ENTRY_ID = 'entry.{ENTRY_ID}'; | |
| // --- End of Configuration --- | |
| // Flag to ensure we only submit the score once per page load. | |
| let hasSubmitted = false; | |
| /** | |
| * Submits the score to the specified Google Form. | |
| * @param {string} score - The score to be submitted. | |
| */ | |
| function submitScoreToGoogleForm(score) { | |
| const data = new URLSearchParams(); | |
| data.append(SCORE_ENTRY_ID, score); | |
| console.log(`Submitting score: ${data.toString()}`); | |
| GM.xmlHttpRequest({ | |
| method: 'POST', | |
| url: GOOGLE_FORM_URL, | |
| headers: { | |
| "Content-Type": "application/x-www-form-urlencoded" | |
| }, | |
| data: data.toString(), | |
| onload: function(response) { | |
| if (response.status === 200) { | |
| console.log('Score submitted successfully!'); | |
| displaySubmissionMessage(`Success! Score (${score}) submitted.`); | |
| } else { | |
| console.error('Submission failed with status:', response.status, response.responseText); | |
| displaySubmissionMessage(`Error: Submission failed. Status: ${response.status}`, true); | |
| } | |
| }, | |
| onerror: function(response) { | |
| console.error('An error occurred during submission:', response.statusText); | |
| displaySubmissionMessage('Error: Could not send score.', true); | |
| } | |
| }); | |
| } | |
| /** | |
| * Displays a message on the game screen to confirm submission status. | |
| * @param {string} message - The text to display. | |
| * @param {boolean} [isError=false] - If true, the message will be styled as an error. | |
| */ | |
| function displaySubmissionMessage(message, isError = false) { | |
| const endScreen = document.querySelector('#game .end'); | |
| if (!endScreen) return; | |
| const messageElement = document.createElement('div'); | |
| messageElement.id = 'submission-status-message'; | |
| messageElement.textContent = message; | |
| messageElement.style.marginTop = '15px'; | |
| messageElement.style.fontWeight = 'bold'; | |
| messageElement.style.fontSize = '1.1em'; | |
| messageElement.style.color = isError ? '#D8000C' : '#4F8A10'; | |
| messageElement.style.backgroundColor = isError ? '#FFD2D2' : '#DFF2BF'; | |
| messageElement.style.padding = '10px'; | |
| messageElement.style.borderRadius = '5px'; | |
| messageElement.style.border = `1px solid ${isError ? '#D8000C' : '#4F8A10'}`; | |
| endScreen.appendChild(messageElement); | |
| } | |
| /** | |
| * Watches for the game-over screen to appear and then submits the score. | |
| */ | |
| function initializeObserver() { | |
| const targetNode = document.getElementById('game'); | |
| if (!targetNode) { | |
| console.error("Zetamac Submitter: Could not find the #game container."); | |
| return; | |
| } | |
| const observer = new MutationObserver((mutationsList, observer) => { | |
| const endScreen = document.querySelector('#game .end'); | |
| const isGameOver = endScreen && endScreen.style.display === 'block'; | |
| // If the game is over and we haven't submitted yet for this page load... | |
| if (isGameOver && !hasSubmitted) { | |
| const scoreElement = endScreen.querySelector('p.correct'); | |
| if (scoreElement) { | |
| const scoreValue = scoreElement.textContent.replace('Score:', '').trim(); | |
| if (scoreValue) { | |
| // Set the flag to true to prevent multiple submissions. | |
| hasSubmitted = true; | |
| // Stop observing now that we've found the score. | |
| observer.disconnect(); | |
| submitScoreToGoogleForm(scoreValue); | |
| } | |
| } | |
| } | |
| }); | |
| const observerConfig = { | |
| attributes: true, | |
| childList: true, | |
| subtree: true, | |
| attributeFilter: ['style'] | |
| }; | |
| observer.observe(targetNode, observerConfig); | |
| console.log('Zetamac Score Submitter is active.'); | |
| } | |
| // Run the script once the page has loaded. | |
| window.addEventListener('load', initializeObserver); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment