Tells you what game to play next so you can maximize your earnings from HTML5 games on GC.
// ==UserScript==
// @name GC Games Optimizer
// @namespace https://greasyfork.org/en/users/1175371/
// @version 0.7
// @description Tells you what game to play next so you can maximize your earnings from HTML5 games on GC.
// @author sanjix
// @match https://www.grundos.cafe/games/html5/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=grundos.cafe
// @grant none
// @license MIT
// ==/UserScript==
var head = document.querySelector('head');
head.innerHTML+= `<style>
#calcOptions {
display: flex;
flex-flow: column;
}
.recommendation {
margin: 1em 0;
display: block;
width: max-content;
}
label {
padding: 5px;
}
#exclusions, #favorites {
display: flex;
flex-flow: column;
flex-wrap: wrap;
height: 300px;
overflow-y: scroll;
border: 1px solid black;
margin: 1em;
width: 580px;
}
#exclusions label:first-child, #favorites label:first-child {
display: block;
font-weight: 800;
}
.topEarners a {
display: block;
}
.featured:before, .featured:after {
content: '***';
}
.featured {
background-color: #0099ff50;
}
</style>`;
var games = [
{
'name': 'Extreme Herder',
'ratio': 71,
'min_score': 1,
'item_score': 85,
'theoretical_max_score': 12920,
'uri': 'extremeherder',
'isPrecise': true,
'topEarner': true
},
{
'name': 'Ultimate Bullseye',
'ratio': 50,
'min_score': 1,
'item_score': 40,
'theoretical_max_score': 850,
'uri': 'bullseye',
'isPrecise': true,
'topEarner': false
},
{
'name': 'Faerie Cloud Racers',
'ratio': 5.1,
'min_score': 29,
'item_score': 625,
'theoretical_max_score': 3205,
'uri': 'faeriecloudracers',
'isPrecise': false,
'topEarner': false
},
{
'name': 'Advert Attack',
'ratio': 6.5,
'min_score': 2,
'item_score': 500,
'theoretical_max_score': 911,
'uri': 'advertattack',
'isPrecise': true,
'topEarner': false
},
{
'name': 'Carnival of Terror',
'ratio': 8.5,
'min_score': 2,
'item_score': 350,
'theoretical_max_score': 1031,
'uri': 'carnivalofterror',
'isPrecise': true,
'topEarner': false
},
{
'name': 'Meepit Juice Break',
'ratio': 4.65,
'min_score': 1,
'item_score': 900,
'theoretical_max_score': 9676,
'uri': 'meepitjuicebreak',
'isPrecise': false,
'topEarner': false
},
{
'name': 'Meerca Chase II',
'ratio': 4.4,
'min_score': 3,
'item_score': 400,
'theoretical_max_score': 4986,
'uri': 'meercachase',
'isPrecise': true,
'topEarner': false
},
{
'name': 'Faerie Bubbles',
'ratio': 5,
'min_score': 3,
'item_score': 400,
'theoretical_max_score': 2727,
'uri': 'faeriebubbles',
'isPrecise': true,
'topEarner': false
},
{
'name': 'Jelly Blobs of Doom',
'ratio': 5.8,
'min_score': 11,
'item_score': 375,
'theoretical_max_score': 24466,
'uri': 'jellyblobs',
'isPrecise': false,
'topEarner': true
},
{
'name': 'Dubloon Disaster',
'ratio': 3.45,
'min_score': 10,
'item_score': 540,
'theoretical_max_score': 35165,
'uri': 'dubloondisaster',
'isPrecise': false,
'topEarner': true
},
{
'name': 'Volcano Run',
'ratio': 3.5,
'min_score': 20,
'item_score': 1650,
'theoretical_max_score': 17940,
'uri': 'volcanorun',
'isPrecise': false,
'topEarner': false
},
{
'name': 'Destruct-O-Match II',
'ratio': 5.15,
'min_score': 2,
'item_score': 1150,
'theoretical_max_score': 12022,
'uri': 'destructomatch',
'isPrecise': true,
'topEarner': false
},
{
'name': 'Korbats Lab',
'ratio': 5.95,
'min_score': 10,
'item_score': 450,
'theoretical_max_score': 12410,
'uri': 'korbatslab',
'isPrecise': false,
'topEarner': true
},
{
'name': 'Suteks Tomb',
'ratio': 6,
'min_score': 1,
'item_score': 800,
'theoretical_max_score': 222276,
'uri': 'sutekstomb',
'isPrecise': true,
'topEarner': true
},
{
'name': 'Ice Cream Machine',
'ratio': 3.1,
'min_score': 5,
'item_score': 2400,
'theoretical_max_score': 23405,
'uri': 'icecreammachine',
'isPrecise': false,
'topEarner': true
},
{
'name': 'Escape from Meridell Castle',
'ratio': 27,
'min_score': 1,
'item_score': 65,
'theoretical_max_score': 4059,
'uri': 'castleescape',
'isPrecise': true,
'topEarner': true
},
{
'name': 'Attack of the Revenge',
'ratio': 8,
'min_score': 2,
'item_score': 250,
'theoretical_max_score': 3636,
'uri': 'attackoftherevenge',
'isPrecise': true,
'topEarner': false
},
{
'name': 'Zurroball',
'ratio': 11,
'min_score': 1,
'item_score': 150,
'theoretical_max_score': 221842,
'uri': 'zurroball',
'isPrecise': true,
'topEarner': true
},
{
'name': 'Usuki Frenzy',
'ratio': 5.5,
'min_score': 15,
'item_score': 350,
'theoretical_max_score': 640,
'uri': 'usukifrenzy',
'isPrecise': false,
'topEarner': false
},
{
'name': 'Revel Roundup',
'ratio': 40,
'min_score': 2,
'item_score': 100,
'theoretical_max_score': 249,
'uri': 'revelroundup',
'isPrecise': true,
'topEarner': false
},
{
'name': 'Igloo Garage Sale - The Game',
'ratio': 10.7,
'min_score': 1,
'item_score': 500,
'theoretical_max_score': 3145,
'uri': 'garagesale',
'isPrecise': true,
'topEarner': false
},
{
'name': 'Splat-A-Sloth',
'ratio': 3,
'min_score': 176,
'item_score': 1500,
'theoretical_max_score': 3930,
'uri': 'splatasloth',
'isPrecise': false,
'topEarner': false
},
{
'name': 'GC Staff Smasher',
'ratio': 7,
'min_score': 1,
'item_score': 813,
'theoretical_max_score': 2771,
'uri': 'staffsmasher',
'isPrecise': true,
'topEarner': false
},
{
'name': 'TNT Staff Smasher',
'ratio': 5,
'min_score': 1,
'item_score': 800,
'theoretical_max_score': 3170,
'uri': 'tntstaffsmasher',
'isPrecise': true,
'topEarner': false
},
{
'name': 'Web of Vernax',
'ratio': 4.5,
'min_score': 2,
'item_score': 850,
'theoretical_max_score': 6141,
'uri': 'webofvernax',
'isPrecise': true,
'topEarner': false
},
{
'name': 'The Buzzer Game',
'ratio': 175,
'min_score': 20,
'item_score': 50,
'theoretical_max_score': 825,
'uri': 'buzzergame',
'isPrecise': false,
'topEarner': true
},
{
'name': 'Hasee Bounce',
'ratio': 65,
'min_score': 1,
'item_score': 50,
'theoretical_max_score': 586,
'uri': 'haseebounce',
'isPrecise': false,
'topEarner': false
},
{
'name': 'Pterattack',
'ratio': 5.2,
'min_score': 5,
'item_score': 700,
'theoretical_max_score': 17645,
'uri': 'pterattack',
'isPrecise': false,
'topEarner': false
},
{
'name': 'Hannah and the Pirate Caves',
'ratio': 0.44,
'min_score': 42000,
'item_score': 15,
'theoretical_max_score': 458800,
'uri': 'piratecaves',
'isPrecise': false,
'topEarner': true
},
{
'name': 'Turmac Roll',
'ratio': 5.5,
'min_score': 8,
'item_score': 600,
'theoretical_max_score': 25795,
'uri': 'turmacroll',
'isPrecise': false,
'topEarner': false
},
{
'name': 'Kass Basher',
'ratio': 5.5,
'min_score': 8,
'item_score': 850,
'theoretical_max_score': 1766,
'uri': 'kassbasher',
'isPrecise': false,
'topEarner': true
},
{
'name': 'Swarm - The Bugs Strike Back',
'ratio': 26,
'min_score': 3,
'item_score': 300,
'theoretical_max_score': 4785,
'uri': 'swarm',
'isPrecise': false,
'topEarner': true
},
{
'name': 'Jubble Bubble',
'ratio': 3,
'min_score': 5,
'item_score': 750,
'theoretical_max_score': 6975,
'uri': 'jubblebubble',
'isPrecise': true,
'topEarner': true
},
{
'name': 'Magma Blaster',
'ratio': 11.5,
'min_score': 2,
'item_score': 250,
'theoretical_max_score': 1062,
'uri': 'magmablaster',
'isPrecise': true,
'topEarner': false
},
{
'name': 'Snowmuncher',
'ratio': 6.5,
'min_score': 9,
'item_score': 950,
'theoretical_max_score': 11064,
'uri': 'snowmuncher',
'isPrecise': true,
'topEarner': false
},
{
'name': 'Neverending Boss Battle',
'ratio': 7.2,
'min_score': 5,
'item_score': 900,
'theoretical_max_score': 39675,
'uri': 'bossbattle',
'isPrecise': false,
'topEarner': false
}
];
games.sort((a,b) => {
const nameA = a.name;
const nameB = b.name;
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
return 0;
});
var gamesInfo = document.querySelector('.games-info');
var calculatorOptions = document.createElement('form');
calculatorOptions.action = 'javascript:void(0);';
calculatorOptions.target = '_self';
calculatorOptions.id = 'calcOptions';
var featuredLabel = document.createElement('label');
featuredLabel.setAttribute('for', 'featured');
featuredLabel.textContent = 'Featured Game:';
var featuredDropdown = document.createElement('select');
featuredDropdown.id = 'featured';
featuredDropdown.form = 'calcOptions';
var itemsLabel = document.createElement('label');
itemsLabel.setAttribute('for', 'items');
itemsLabel.textContent = 'Game for Items:';
var itemsDropdown = document.createElement('select');
itemsDropdown.form = 'calcOptions';
itemsDropdown.id = 'items';
var favoritesDiv = document.createElement('div');
favoritesDiv.id = 'favorites';
var favoritesLabel = document.createElement('label');
favoritesLabel.setAttribute('for', 'exclusions');
favoritesLabel.append('Prefer:');
favoritesDiv.appendChild(favoritesLabel);
games.forEach((game) => {
var featuredOptions = document.createElement('option');
featuredOptions.value = game.name;
featuredOptions.textContent = game.name;
var itemsOptions = document.createElement('option');
itemsOptions.value = game.name;
itemsOptions.textContent = game.name;
featuredDropdown.add(featuredOptions);
itemsDropdown.add(itemsOptions);
var checkboxItem = document.createElement('input');
var checkboxLabel = document.createElement('label');
checkboxItem.setAttribute('type', 'checkbox');
checkboxItem.setAttribute('name', 'fave');
checkboxItem.setAttribute('muptliple', '');
checkboxItem.setAttribute('id', 'fave-' + game.name);
checkboxItem.setAttribute('value', game.name);
checkboxLabel.setAttribute('for', 'fave-' + game.name);
checkboxLabel.appendChild(checkboxItem);
checkboxLabel.append(game.name);
favoritesDiv.appendChild(checkboxLabel);
});
var exclusionsDiv = document.createElement('div');
exclusionsDiv.id = 'exclusions';
var exclusionsLabel = document.createElement('label');
exclusionsLabel.setAttribute('for', 'exclusions');
exclusionsLabel.append('Exclude:');
exclusionsDiv.appendChild(exclusionsLabel);
games.forEach((game) => {
var featuredOptions = document.createElement('option');
featuredOptions.value = game.name;
featuredOptions.textContent = game.name;
var itemsOptions = document.createElement('option');
itemsOptions.value = game.name;
itemsOptions.textContent = game.name;
featuredDropdown.add(featuredOptions);
itemsDropdown.add(itemsOptions);
var checkboxItem = document.createElement('input');
var checkboxLabel = document.createElement('label');
checkboxItem.setAttribute('type', 'checkbox');
checkboxItem.setAttribute('name', 'exclude');
checkboxItem.setAttribute('muptliple', '');
checkboxItem.setAttribute('id', 'excl-' + game.name);
checkboxItem.setAttribute('value', game.name);
checkboxLabel.setAttribute('for', 'excl-' + game.name);
checkboxLabel.appendChild(checkboxItem);
checkboxLabel.append(game.name);
exclusionsDiv.appendChild(checkboxLabel);
});
calculatorOptions.appendChild(featuredLabel);
calculatorOptions.appendChild(featuredDropdown);
calculatorOptions.appendChild(itemsLabel);
calculatorOptions.appendChild(itemsDropdown);
calculatorOptions.appendChild(favoritesDiv);
calculatorOptions.appendChild(exclusionsDiv);
var submitSettings = document.createElement('button');
submitSettings.textContent = 'Update Calculator';
submitSettings.target = "_self";
calculatorOptions.appendChild(submitSettings);
// console.log('mb?');
gamesInfo.after(calculatorOptions);
let recommendation = document.createElement('a');
recommendation.classList = 'recommendation';
// console.log('plz');
function removeCommas(score) {
return score.replace(',', '');
}
function findNextGame(form) {
var exclusions = form.getAll('exclude');
var favorites = form.getAll('fave');
var currentNP = form.get('score');
var featured = form.get('featured');
var npTheoMax = parseInt(removeCommas(document.querySelector('.games-info #np_earned ~ strong').textContent));
// var isCS = formData.get('cs');
var npToEarn = npTheoMax - currentNP;
function isFeatured(game) {
return game.name == form.get('featured');
}
function findMultiplier(game) {
if (npTheoMax == 60000) {
return 1;
} else if (npTheoMax == 120000 && isFeatured(game)) {
return 3;
} else if (npTheoMax == 120000 || isFeatured(game)) {
return 2;
}
}
function pointsToEarn(game) {
// console.log(Math.floor((npTheoMax - currentNP)/game.ratio));
return Math.floor(npToEarn/(game.ratio/findMultiplier(game)));
}
function isPossible(game) {
console.log(game.name, pointsToEarn(game), game.min_score);
// console.log(pointsToEarn(game) >= game.min_score);
return pointsToEarn(game) >= game.min_score && pointsToEarn(game);
}
function isAchievable(game) {
return npToEarn % game.ratio == 0 && pointsToEarn(game) % game.min_score == 0 && game.isPrecise;
}
function isEasyMath() {
console.log(npToEarn);
return npToEarn % 5 == 0 || npToEarn % 10 == 0;
}
let itemsEarned = parseInt(document.querySelector('.games-info #items_earned').textContent);
let itemsMax = parseInt(document.querySelector('.games-info #items_earned ~ strong').textContent);
let gameCandidate;
console.log(itemsEarned, itemsMax);
console.log(favorites);
console.log(exclusions);
if (npToEarn == 0) {
return undefined;
} else if (itemsEarned < itemsMax) {
return 'items';
} else { //items already earned
if (favorites != undefined) { //check if preferred games playable
let faves = games.filter((game) => (favorites.includes(game.name)));
console.log(faves);
for (let i = 0; i < faves.length; i++) {
if (isPossible(faves[i])) {
if ((gameCandidate == undefined) || (pointsToEarn(faves[i]) < pointsToEarn(gameCandidate))) {
gameCandidate = faves[i];
}
}
}
}
if (gameCandidate != undefined) {
return gameCandidate;
} else if (isEasyMath()) { //check if easy math option
return games.find((game) => game.name == 'TNT Staff Smasher');
}
//check remaining games (minus exclusions)
let minusExclGames = games.filter((game) => !(exclusions.includes(game.name)));
for (let i = 0; i < minusExclGames.length; i++) {
console.log(minusExclGames[i].name, npToEarn, minusExclGames[i].ratio);
console.log(isPossible(minusExclGames[i]));
console.log(npToEarn % minusExclGames[i].ratio == 0);
if (npToEarn % minusExclGames[i].ratio == 0) {
if (isPossible(minusExclGames[i]) && isAchievable(minusExclGames[i])) {
return minusExclGames[i];
}
} else if (pointsToEarn(minusExclGames[i]) > 0 && isPossible(minusExclGames[i])) {
if ((gameCandidate == undefined) || (pointsToEarn(minusExclGames[i]) < pointsToEarn(gameCandidate))) {
gameCandidate = minusExclGames[i]
}
}
}
return gameCandidate;
}
}
calculatorOptions.addEventListener('submit', (event) => {
event.preventDefault();
// console.log('hello world');
//var settings = event.formData;
var score = parseInt(removeCommas(document.querySelector('.games-info #np_earned').textContent));
let formData = new FormData(calculatorOptions);
var feat = document.querySelector('#featured').selectedOptions[0].value;
var items = document.querySelector('#items').selectedOptions[0].value;
formData.append('featured', feat);
formData.append('items', items);
formData.append('score', score);
console.log(formData);
//current game page
var thisGame = document.querySelector('h1').textContent;
//check for compsci
var npTheoMax = parseInt(removeCommas(document.querySelector('.games-info #np_earned ~ strong').textContent));
var multiplier = 1;
var npPracMax = 120000;
switch (npTheoMax) {
case 120000:
npPracMax+= 120000;
multiplier = 2;
break;
case 60000:
npPracMax += 60000;
break;
}
if (thisGame == feat) {
npPracMax += 60000;
if (multiplier == 2) {
multiplier = 3
} else {
multiplier = 2
}
console.log(multiplier);
}
let next = findNextGame(formData);
if (next == 'items') {
recommendation.innerHTML = `You should play ` + items + ` next! Earn your daily items!`;
recommendation.href = `https://grundos.cafe/games/html5/` + games.find(game => game.name == items.valueOf()).uri;
} else if (next === undefined) {
recommendation.innerHTML = `Go for broke! You've earned as much as possible.`;
var chooseYourFighter = document.createElement('div');
chooseYourFighter.classList = 'topEarners';
games.filter((game) => game.topEarner).forEach((game) => {
chooseYourFighter.innerHTML += `<a target="_blank"` + (game.name == feat ? `class= "featured" ` : ``) + `href="https://grundos.cafe/games/html5/` + game.uri + `">` + game.name + `</a>`;
});
} else {
recommendation.innerHTML = `You should play ` + next.name + ` next! Earn ` + Math.floor((npTheoMax - score)/next.ratio/multiplier) + ` point(s), then calculate again.`;
recommendation.href = `https://grundos.cafe/games/html5/` + next.uri;
console.log(next.name);
}
recommendation.target = '_blank';
calculatorOptions.after(recommendation);
if (chooseYourFighter) {
recommendation.after(chooseYourFighter);
}
});