Skip to content

Instantly share code, notes, and snippets.

@CarterT27
Last active July 22, 2025 02:39
Show Gist options
  • Select an option

  • Save CarterT27/54759dae04dc42297eb025cc520f37c4 to your computer and use it in GitHub Desktop.

Select an option

Save CarterT27/54759dae04dc42297eb025cc520f37c4 to your computer and use it in GitHub Desktop.
Zetamac Score Tracker
// ==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