Fixed prediction: uses correct + incorrect from payload
// ==UserScript==
// @name MathsOnline HACKS!! {CHEAT} {HACKS} {EXPLOIT} {API} {DECOMPILED}
// @namespace http://tampermonkey.net/
// @version 3.0
// @description Fixed prediction: uses correct + incorrect from payload
// @author Phil 🥹👍 & DynaHacks
// @license MIT
// @match *://*.mathsonline.com.au/*
// @grant none
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
// ---------- GLOBALS ----------
let latestAnswers = [];
let hudContainer = null;
let hudContent = null;
let isHidden = false;
let progressData = { pointsCompleted: 0, pointsRequired: 0, totalCorrect: 0, totalIncorrect: 0 };
let cachedSvgContent = '';
let svgVisible = false;
let dynamicValues = {
userQuestionSetId: null,
worksheetId: null,
taskId: null,
menuId: null,
diagnosticTypeId: null,
tutorial: null,
tutorialMaster: null,
svgInteractiveId: null
};
// ---------- STYLES ----------
const styles = `
#hacks-hud {
position: fixed;
top: 20px;
right: 20px;
width: 340px;
background: rgba(20, 20, 20, 0.95);
color: #ffffff;
border: 1px solid #00ff00;
border-radius: 8px;
font-family: monospace;
box-shadow: 0 0 15px rgba(0, 255, 0, 0.2);
z-index: 999999;
transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out;
user-select: none;
font-size: 12px;
}
#hacks-hud-header {
background: #111;
padding: 8px 12px;
font-weight: bold;
font-size: 12px;
border-bottom: 1px solid #333;
display: flex;
justify-content: space-between;
align-items: center;
cursor: grab;
}
#hacks-hud-header:active { cursor: grabbing; }
#hacks-hud-title { color: #00ff00; font-size: 11px; }
#hacks-hud-btn-group { display: flex; gap: 6px; }
.hacks-hud-btn {
background: #333;
border: 1px solid #555;
color: #aaa;
padding: 2px 8px;
border-radius: 3px;
cursor: pointer;
font-size: 10px;
font-family: monospace;
}
.hacks-hud-btn:hover { background: #444; color: #fff; }
#hacks-hud-spoof-btn { border-color: #00ff00; color: #00ff00; }
#hacks-hud-spoof-btn:hover { background: #00ff00; color: #000; }
#hacks-hud-svg-btn { border-color: #ffaa00; color: #ffaa00; }
#hacks-hud-svg-btn:hover { background: #ffaa00; color: #000; }
#hacks-hud-body { padding: 10px 12px; max-height: 350px; overflow-y: auto; font-size: 11px; }
.hacks-answer-row {
display: flex;
justify-content: space-between;
padding: 4px 0;
border-bottom: 1px solid #222;
}
.hacks-answer-row:last-child { border-bottom: none; }
.hacks-label { color: #888; }
.hacks-val { color: #00ff00; font-weight: bold; }
.hacks-progress {
background: #111;
padding: 6px 10px;
border-radius: 4px;
margin-bottom: 8px;
font-size: 11px;
border-left: 2px solid #00ff00;
}
.hacks-progress-bar {
background: #222;
height: 4px;
border-radius: 2px;
margin-top: 4px;
overflow: hidden;
}
.hacks-progress-bar-fill {
height: 100%;
background: #00ff00;
border-radius: 2px;
transition: width 0.3s ease;
}
.hacks-hidden-hud {
opacity: 0 !important;
pointer-events: none !important;
transform: scale(0.95) translateY(-10px);
}
.hacks-progress-text {
display: flex;
justify-content: space-between;
color: #aaa;
}
.hacks-progress-text span:first-child { color: #00ff00; }
.hacks-progress-text span:last-child { color: #888; }
.hacks-status-ok { color: #00ff00; }
.hacks-status-warning { color: #ffaa00; }
.hacks-section-title {
color: #888;
font-size: 10px;
text-transform: uppercase;
letter-spacing: 1px;
margin: 8px 0 4px 0;
border-bottom: 1px solid #222;
padding-bottom: 2px;
}
.hacks-prediction {
margin-top: 6px;
border-top: 1px solid #222;
padding-top: 6px;
}
.hacks-prediction-label {
color: #888;
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.hacks-prediction-value {
font-weight: bold;
font-size: 14px;
color: #00ff00;
}
`;
function injectStyles() {
if (document.getElementById('hacks-styles')) return;
const styleSheet = document.createElement('style');
styleSheet.id = 'hacks-styles';
styleSheet.innerText = styles;
document.head.appendChild(styleSheet);
}
// ---------- PREDICTION ----------
function updatePrediction() {
const totalCorrect = parseInt(progressData.totalCorrect) || 0;
const totalIncorrect = parseInt(progressData.totalIncorrect) || 0;
const totalAnswered = totalCorrect + totalIncorrect;
const pointsRequired = parseInt(progressData.pointsRequired) || 1;
const pointsCompleted = parseInt(progressData.pointsCompleted) || 0;
const container = document.getElementById('hacks-prediction-value');
if (!container) return;
if (totalAnswered === 0) {
container.textContent = '—';
container.style.color = '#888';
return;
}
const accuracy = totalCorrect / totalAnswered;
const predicted = Math.round(accuracy * pointsRequired);
const finalPrediction = Math.min(predicted, pointsRequired);
container.textContent = `${finalPrediction} / ${pointsRequired} (${Math.round(accuracy * 100)}%)`;
container.style.color = accuracy >= 0.8 ? '#00ff00' : accuracy >= 0.5 ? '#ffaa00' : '#ff6b6b';
}
// ---------- SVG TOGGLE ----------
function toggleSVG() {
const container = document.getElementById('hacks-answers-container');
if (!container) return;
const existing = document.getElementById('hacks-svg-placeholder');
if (existing) {
existing.remove();
return;
}
const div = document.createElement('div');
div.id = 'hacks-svg-placeholder';
div.style.cssText = 'color:#888;font-size:11px;margin-top:6px;padding:6px;border:1px solid #333;border-radius:4px;background:#111;';
div.textContent = 'SVG toggle — no SVG available (or not implemented in this version)';
container.appendChild(div);
}
// ---------- DETECTION ----------
function getTutorialFromPage() {
const urlParams = new URLSearchParams(window.location.search);
let tutorial = urlParams.get('tutorial') || urlParams.get('tutorialId');
if (!tutorial) {
const pathParts = window.location.pathname.split('/');
for (let i = 0; i < pathParts.length; i++) {
if (pathParts[i] === 'lessons' && pathParts[i+1]) {
tutorial = pathParts[i+2] || pathParts[i+1];
break;
}
}
}
if (!tutorial && typeof window.tutorial !== 'undefined') tutorial = window.tutorial;
if (!tutorial && window.currentQuestionSet) tutorial = window.currentQuestionSet.tutorial;
return tutorial || null;
}
function getTutorialMasterFromPage() {
const urlParams = new URLSearchParams(window.location.search);
let tutorialMaster = urlParams.get('tutorialMaster') || urlParams.get('tutorialmaster');
if (!tutorialMaster && typeof window.tutorialMaster !== 'undefined') tutorialMaster = window.tutorialMaster;
if (!tutorialMaster && window.currentQuestionSet) tutorialMaster = window.currentQuestionSet.tutorialMaster;
if (!tutorialMaster) {
for (let key in window) {
if (key.toLowerCase().includes('tutorialmaster') || key.toLowerCase().includes('tutorial_master')) {
const val = window[key];
if (typeof val === 'string' && /^\d+$/.test(val)) {
tutorialMaster = val;
break;
}
}
}
}
return tutorialMaster || null;
}
// ---------- HUD ----------
function createHUD() {
if (document.getElementById('hacks-hud')) return;
hudContainer = document.createElement('div');
hudContainer.id = 'hacks-hud';
hudContainer.innerHTML = `
<div id="hacks-hud-header">
<span id="hacks-hud-title">MathsOnline Hacks v2.8.6</span>
<div id="hacks-hud-btn-group">
<button class="hacks-hud-btn" id="hacks-hud-spoof-btn">SPOOF</button>
<button class="hacks-hud-btn" id="hacks-hud-svg-btn">SVG</button>
<button class="hacks-hud-btn" id="hacks-hud-toggle-btn">HIDE</button>
</div>
</div>
<div id="hacks-hud-body">
<div id="hacks-progress-container" style="display:none;"></div>
<div id="hacks-answers-container">
<div style="color: #888; text-align: center;">Awaiting question...</div>
</div>
<div class="hacks-prediction">
<div class="hacks-prediction-label">📊 PREDICTED SCORE</div>
<div id="hacks-prediction-value" class="hacks-prediction-value">—</div>
</div>
</div>
`;
document.documentElement.appendChild(hudContainer);
hudContent = document.getElementById('hacks-hud-body');
document.getElementById('hacks-hud-toggle-btn').addEventListener('click', toggleHUD);
document.getElementById('hacks-hud-spoof-btn').addEventListener('click', spoofAnswers);
document.getElementById('hacks-hud-svg-btn').addEventListener('click', toggleSVG);
makeDraggable(hudContainer);
console.log('[HUD] Created v2.8.6');
}
function ensureHUD() {
if (!document.getElementById('hacks-hud')) {
console.log('[HUD] Re-injecting...');
createHUD();
if (isHidden && hudContainer) {
hudContainer.classList.add('hacks-hidden-hud');
}
}
}
const observer = new MutationObserver(() => ensureHUD());
observer.observe(document.documentElement, { childList: true, subtree: true });
setInterval(ensureHUD, 3000);
function makeDraggable(element) {
const header = document.getElementById('hacks-hud-header');
if (!header) return;
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
header.onmousedown = dragMouseDown;
function dragMouseDown(e) {
if (e.target.classList && e.target.classList.contains('hacks-hud-btn')) return;
e = e || window.event;
e.preventDefault();
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
element.style.top = (element.offsetTop - pos2) + "px";
element.style.left = (element.offsetLeft - pos1) + "px";
element.style.right = "auto";
}
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
}
}
function toggleHUD() {
isHidden = !isHidden;
if (hudContainer) {
hudContainer.classList.toggle('hacks-hidden-hud', isHidden);
}
}
window.addEventListener('keydown', (e) => {
if (e.key.toLowerCase() === 'h' && !e.ctrlKey && !e.metaKey) {
toggleHUD();
}
});
// ---------- UPDATE FUNCTIONS ----------
function updateProgress(pointsCompleted, pointsRequired, totalCorrect, totalIncorrect) {
progressData.pointsCompleted = pointsCompleted;
progressData.pointsRequired = pointsRequired;
progressData.totalCorrect = totalCorrect;
progressData.totalIncorrect = totalIncorrect;
const progressContainer = document.getElementById('hacks-progress-container');
if (!progressContainer) return;
if (pointsRequired > 0) {
progressContainer.style.display = 'block';
const percent = Math.min((pointsCompleted / pointsRequired) * 100, 100);
progressContainer.innerHTML = `
<div class="hacks-progress">
<div class="hacks-progress-text">
<span>${pointsCompleted}</span>
<span>/${pointsRequired} points</span>
<span style="color:#888;">✔ ${totalCorrect} | ✘ ${totalIncorrect}</span>
</div>
<div class="hacks-progress-bar">
<div class="hacks-progress-bar-fill" style="width:${percent}%;"></div>
</div>
</div>
`;
} else {
progressContainer.style.display = 'none';
}
updatePrediction();
}
function updateHUD(answers) {
if (!hudContent) return;
const answersContainer = document.getElementById('hacks-answers-container');
if (!answersContainer) return;
if (!answers || answers.length === 0) {
answersContainer.innerHTML = `<div style="color: #888; text-align: center;">⏳ No answers captured yet.</div>`;
return;
}
let html = `<div class="hacks-section-title">Answers</div>`;
answers.forEach((item, idx) => {
html += `
<div class="hacks-answer-row">
<span class="hacks-label">Q${idx+1}:</span>
<span class="hacks-val">${item.Answer}</span>
</div>
`;
});
html += `<div style="margin-top:6px;text-align:right;font-size:10px;color:#555;">${answers.length} answer(s) ready</div>`;
answersContainer.innerHTML = html;
latestAnswers = answers;
}
// ---------- INTERCEPTOR ----------
function analyzeAndProcess(rawText) {
const trimmed = rawText.trim();
if (trimmed.startsWith('{') && (trimmed.includes('"components"') || trimmed.includes('"userQuestionSetId"'))) {
try {
const data = JSON.parse(trimmed);
if (data.userQuestionSetId) dynamicValues.userQuestionSetId = data.userQuestionSetId;
if (data.worksheetId) dynamicValues.worksheetId = data.worksheetId;
if (data.taskId) dynamicValues.taskId = data.taskId;
if (data.menuId) dynamicValues.menuId = data.menuId;
if (data.diagnosticTypeId) dynamicValues.diagnosticTypeId = data.diagnosticTypeId;
if (data.tutorial) dynamicValues.tutorial = data.tutorial;
if (data.tutorialMaster) dynamicValues.tutorialMaster = data.tutorialMaster;
if (data.svgInteractiveId) dynamicValues.svgInteractiveId = data.svgInteractiveId;
if (data.pointsCompleted !== undefined) {
updateProgress(
parseInt(data.pointsCompleted) || 0,
parseInt(data.pointsRequired) || 0,
parseInt(data.correct) || 0,
parseInt(data.incorrect) || 0
);
}
if (data && data.components) {
const answersFound = [];
data.components.forEach(comp => {
if (comp.ComponentTypeID === "2" && comp.Data) {
try {
const parsedData = JSON.parse(comp.Data);
if (parsedData.Answers) {
answersFound.push({
ComponentID: comp.ComponentID,
Answer: parsedData.Answers
});
}
} catch (innerErr) {}
}
});
if (answersFound.length > 0) {
updateHUD(answersFound);
}
}
} catch (e) {}
}
}
const originalFetch = window.fetch;
window.fetch = async function(...args) {
const response = await originalFetch(...args);
try {
const clone = response.clone();
const text = await clone.text();
analyzeAndProcess(text);
} catch (e) {}
return response;
};
const originalOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
this.addEventListener('readystatechange', function() {
if (this.readyState === 4 && this.status === 200) {
try {
analyzeAndProcess(this.responseText);
} catch (e) {}
}
});
return originalOpen.apply(this, arguments);
};
// ---------- SPOOF ----------
async function spoofAnswers() {
if (!latestAnswers || latestAnswers.length === 0) {
alert('No answers captured yet. Wait for a question to load.');
return;
}
const tutorial = dynamicValues.tutorial || getTutorialFromPage();
const tutorialMaster = dynamicValues.tutorialMaster || getTutorialMasterFromPage();
const userQuestionSetId = dynamicValues.userQuestionSetId;
const worksheetId = dynamicValues.worksheetId || '0';
const taskId = dynamicValues.taskId || '0';
const menuId = dynamicValues.menuId || '102';
const diagnosticTypeId = dynamicValues.diagnosticTypeId || '0';
const svgInteractiveId = dynamicValues.svgInteractiveId || null;
if (!userQuestionSetId) {
alert('No userQuestionSetId captured. Wait for a question to load first.');
return;
}
if (!tutorial || !tutorialMaster) {
alert('Could not detect tutorial or tutorialMaster.');
return;
}
const inputData = [{
questionId: 1,
inputs: latestAnswers.map((item, idx) => ({
id: `input${idx+1}`,
value: item.Answer,
correct: "true"
})),
checkboxes: [],
radiobuttons: [],
selectables: [],
draggables: [],
marks: latestAnswers.map((item, idx) => ({
id: `mark${idx+1}`,
correct: "true"
})),
solutions: []
}];
const payload = {
userQuestionSetId: userQuestionSetId,
svgInteractiveId: svgInteractiveId,
tutorial: tutorial,
tutorialMaster: tutorialMaster,
menuId: menuId,
worksheetId: worksheetId,
taskId: taskId,
diagnosticTypeId: diagnosticTypeId,
userQuestionSetTypeId: '7',
difficulty: '1',
correct: latestAnswers.length,
incorrect: 0,
duration: Math.floor(8000 + Math.random() * 15000),
data: JSON.stringify(inputData)
};
try {
const submitRes = await fetch(
`https://www.mathsonline.com.au/ajax/svg_interactives/submitResult?r=${Math.random()}`,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest'
},
body: new URLSearchParams(payload)
}
);
const rawText = await submitRes.text();
try {
const result = JSON.parse(rawText);
if (result.pointsCompleted !== undefined) {
updateProgress(
parseInt(result.pointsCompleted) || 0,
parseInt(result.pointsRequired) || 0,
parseInt(result.correct) || 0,
parseInt(result.incorrect) || 0
);
}
alert(`Submitted ${latestAnswers.length} answer(s)! Points: ${progressData.pointsCompleted}/${progressData.pointsRequired}`);
setTimeout(() => window.location.reload(), 800);
} catch (parseError) {
alert(`Server error:\n${rawText.substring(0, 100)}`);
}
} catch (e) {
alert('Spoof failed — check console.');
}
}
// ---------- INIT ----------
window.addEventListener('DOMContentLoaded', () => {
injectStyles();
createHUD();
console.log('[INIT] Tutorial:', getTutorialFromPage(), 'Master:', getTutorialMasterFromPage());
});
console.log('%c[MathsOnline ULTIMATE] Loaded v2.8.6', 'color: #00ff00; font-weight: bold;');
})();