375 lines
15 KiB
JavaScript
375 lines
15 KiB
JavaScript
// ==UserScript==
|
|
// @name IITC plugin: ResTools BB Watch Reloaded
|
|
// @namespace https://git.martinvylet.cz/vykend/ResTools-BB-Watch-Reloaded
|
|
// @version 0.3
|
|
// @description Scan window for BBs on ornamented portals, then check results
|
|
// @author vikend
|
|
// @icon
|
|
// @updateURL https://git.martinvylet.cz/vykend/ResTools-BB-Watch-Reloaded/raw/branch/main/RestoolsBBWatchReloaded.js
|
|
// @downloadURL https://git.martinvylet.cz/vykend/ResTools-BB-Watch-Reloaded/raw/branch/main/RestoolsBBWatchReloaded.js
|
|
// @match https://intel.ingress.com/*
|
|
// @grant none
|
|
// ==/UserScript==
|
|
/* globals $, L, dialog */
|
|
|
|
|
|
function wrapper(plugin_info)
|
|
{
|
|
'use strict';
|
|
|
|
// Default definitions for IITC plugin
|
|
if (typeof window.plugin !== 'function') window.plugin = function() {};
|
|
|
|
|
|
// ##### PLUGIN START #####
|
|
window.plugin.restoolsBBWatchReloaded = function() {};
|
|
|
|
window.plugin.restoolsBBWatchReloaded.LAYERS = {};
|
|
window.plugin.restoolsBBWatchReloaded.LAYERGROUP = null;
|
|
window.plugin.restoolsBBWatchReloaded.BB_STORAGE = 'plugin-restools-bbwatch-reloaded';
|
|
window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS = [[[],[]],[[],[]],[[],[]],[[],[]],[[],[]],[[],[]],[[],[]]];
|
|
//struct of WAVE_PORTALS: [ wave: [ ornamented[], results[] ] ]
|
|
|
|
//edit this with start times according to YOUR local times (ie. as seen in COMM)
|
|
window.plugin.restoolsBBWatchReloaded.TIMETABLE = {
|
|
wave1: "14:00",
|
|
wave2: "14:25",
|
|
wave3: "14:50",
|
|
wave4: "15:15",
|
|
wave5: "15:40",
|
|
wave6: "16:05",
|
|
wave7: "16:30",
|
|
wave8: "16:55" //needed for calculations, put there end of wave 7
|
|
};
|
|
|
|
|
|
// --- CSS ---
|
|
window.plugin.restoolsBBWatchReloaded.setupCSS = function() {
|
|
$("<style>")
|
|
.prop("type", "text/css")
|
|
.html(`
|
|
.styled-table {
|
|
border-collapse: collapse;
|
|
margin: 25px 0;
|
|
font-size: 0.9em;
|
|
font-family: sans-serif;
|
|
min-width: 400px;
|
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
|
|
}
|
|
.styled-table thead tr {
|
|
background-color: #9452a5;
|
|
color: #ffffff;
|
|
text-align: left;
|
|
}
|
|
.styled-table th,
|
|
.styled-table td {
|
|
padding: 12px 15px;
|
|
}
|
|
.styled-table tbody tr {
|
|
border-bottom: 1px solid #9452a5;
|
|
}
|
|
|
|
.styled-table tbody tr:last-of-type {
|
|
border-bottom: 2px solid #9452a5;
|
|
}
|
|
|
|
`)
|
|
.appendTo("head");
|
|
}
|
|
|
|
// --- HELPER
|
|
window.plugin.restoolsBBWatchReloaded.getCurrentWaveNo = function() {
|
|
const currentTime = new Date();
|
|
const currentTimeString = currentTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
const currentTimePlus5Minutes = (new Date(currentTime.getTime() + 5 * 60000)).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });// Adding 20 minutes in milliseconds
|
|
|
|
let currentWave = 0;
|
|
let battleOver = false;
|
|
|
|
// Iterate through the waves in the timetable
|
|
for (const wave in window.plugin.restoolsBBWatchReloaded.TIMETABLE) {
|
|
if (currentTimeString < window.plugin.restoolsBBWatchReloaded.TIMETABLE[wave]) {
|
|
if (currentTimePlus5Minutes > window.plugin.restoolsBBWatchReloaded.TIMETABLE[wave]) {
|
|
|
|
battleOver = true;
|
|
}
|
|
break;
|
|
}
|
|
currentWave++;
|
|
}
|
|
return [currentWave, battleOver];
|
|
|
|
}
|
|
|
|
|
|
// --- UPDATE ---
|
|
window.plugin.restoolsBBWatchReloaded.updateCurrentState = function()
|
|
{
|
|
let wavePortals = [];
|
|
|
|
// Find ornaments
|
|
for (let portalGuid in window.portals)
|
|
{
|
|
let portal = window.portals[portalGuid];
|
|
|
|
if (portal.options.data.hasOwnProperty('ornaments'))
|
|
{
|
|
let ornaments = portal.options.data.ornaments;
|
|
|
|
if (ornaments.indexOf("ap1") != -1 || ornaments.indexOf("peBN_RES_WINNER") != -1 || ornaments.indexOf("peBN_ENL_WINNER") != -1)
|
|
{
|
|
let portalUpload = {
|
|
Guid: portal.options.guid,
|
|
IsOrnamented: (ornaments.indexOf("ap1") != -1),
|
|
IsVolatile: (ornaments.indexOf("ap1_v") != -1),
|
|
IsWinnerRes: (ornaments.indexOf("peBN_RES_WINNER") != -1),
|
|
IsWinnerEnl: (ornaments.indexOf("peBN_ENL_WINNER") != -1),
|
|
IsBeaconActive: (ornaments.indexOf("peBB_BATTLE_RARE") != -1),
|
|
Beacons: ornaments.join(','),
|
|
};
|
|
wavePortals.push(portalUpload);
|
|
}
|
|
}
|
|
}
|
|
|
|
window.plugin.restoolsBBWatchReloaded.addNewPortals(wavePortals);
|
|
|
|
// Automatic update
|
|
setTimeout(window.plugin.restoolsBBWatchReloaded.updateCurrentState, 30 * 1000);
|
|
}
|
|
|
|
// --- CHECK IF ALREADY RECORDED, STORE IF NOT
|
|
window.plugin.restoolsBBWatchReloaded.addNewPortals = function(wavePortals)
|
|
{
|
|
let wave = window.plugin.restoolsBBWatchReloaded.getCurrentWaveNo();
|
|
let waveBattleOver = Number(wave[1]);
|
|
let waveNo = wave[0] -1;
|
|
|
|
if (waveNo < 0) {
|
|
console.log("BBWatchReloaded: According to timetable anomaly haven't started yet, skipping");
|
|
return;
|
|
}
|
|
let portalsToBeAdded = [];
|
|
for (let i in wavePortals)
|
|
{
|
|
let portal = wavePortals[i];
|
|
//this should record all ornamented portals in each wave.
|
|
//plugin considers 5-minute-window at the end of each wave (or before start of the next one) as window where to check for BBs results
|
|
// = records ornamented portals to another array
|
|
if(portal.IsOrnamented) {
|
|
if (!(window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS[waveNo][waveBattleOver].find((obj) => obj.Guid === portal.Guid))) {
|
|
portalsToBeAdded.push(portal);
|
|
}
|
|
}
|
|
|
|
//if ornaments disappear too quickly, it is needed to add 2nd check
|
|
//has the portal winners beacon?
|
|
//if yes, was it ornamented?
|
|
|
|
if(portal.IsWinnerRes || portal.IsWinnerEnl) {
|
|
//check if portal wasnt already added in previous waves
|
|
if (!(window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS[waveNo][waveBattleOver].find((obj) => obj.Guid === portal.Guid))) {
|
|
|
|
//check if portal isn't already in portalsToBeAdded
|
|
if (!(portalsToBeAdded.find((obj) => obj.Guid === portal.Guid))) {
|
|
|
|
//check if portal was added as ornamented before
|
|
if ((window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS[waveNo][0].find((obj) => obj.Guid === portal.Guid))) {
|
|
portalsToBeAdded.push(portal);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS[waveNo][waveBattleOver] = window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS[waveNo][waveBattleOver].concat(portalsToBeAdded);
|
|
window.plugin.restoolsBBWatchReloaded.saveStorage(window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS);
|
|
console.log("BBWatchReloaded: Portals updated");
|
|
}
|
|
|
|
window.plugin.restoolsBBWatchReloaded.computeBeacons = function(wave) {
|
|
let ornamented = window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS[wave][0];
|
|
let results = window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS[wave][1];
|
|
let resWin = 0;
|
|
let resVolatiles = 0;
|
|
let enlWin = 0;
|
|
let enlVolatiles = 0;
|
|
for (let i in results) {
|
|
let portal = results[i];
|
|
if (ornamented.find((obj) => obj.Guid === portal.Guid)) {
|
|
if (portal.IsWinnerRes) {
|
|
resWin++;
|
|
if (portal.IsVolatile) {
|
|
resVolatiles++;
|
|
}
|
|
}
|
|
else if (portal.IsWinnerEnl) {
|
|
enlWin++;
|
|
if (portal.IsVolatile) {
|
|
enlVolatiles++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
let objResults = {
|
|
resWin: resWin,
|
|
enlWin: enlWin,
|
|
resVolatiles: resVolatiles,
|
|
enlVolatiles: enlVolatiles
|
|
}
|
|
|
|
return objResults;
|
|
|
|
}
|
|
|
|
window.plugin.restoolsBBWatchReloaded.getCurrentState = function()
|
|
{
|
|
let waves = [];
|
|
for (let i in window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS) {
|
|
let results = window.plugin.restoolsBBWatchReloaded.computeBeacons(i);
|
|
let wave = {
|
|
WaveNumber: Number(i) +1,
|
|
volatilesCount: 0,
|
|
beaconCount: window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS[i][0].length,
|
|
PercentageRes: window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS[i][0].length/results.resWin,
|
|
PercentageEnl: window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS[i][0].length/results.enlWin,
|
|
BeaconsWonRes: results.resWin,
|
|
BeaconsWonResVolatiles: results.resVolatiles,
|
|
BeaconsWonEnl: results.enlWin,
|
|
BeaconsWonEnlVolatiles: results.enlVolatiles
|
|
};
|
|
waves.push(wave);
|
|
}
|
|
window.plugin.restoolsBBWatchReloaded.showDialog(waves);
|
|
}
|
|
|
|
// --- STORAGE
|
|
|
|
window.plugin.restoolsBBWatchReloaded.saveStorage = function(objToStore) {
|
|
localStorage[window.plugin.restoolsBBWatchReloaded.BB_STORAGE] = JSON.stringify(objToStore);
|
|
}
|
|
|
|
window.plugin.restoolsBBWatchReloaded.loadStorage = function() {
|
|
if (JSON.parse(localStorage[window.plugin.restoolsBBWatchReloaded.BB_STORAGE]) != null) {
|
|
return JSON.parse(localStorage[window.plugin.restoolsBBWatchReloaded.BB_STORAGE]);
|
|
}
|
|
else {
|
|
return window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS;
|
|
}
|
|
}
|
|
|
|
window.plugin.restoolsBBWatchReloaded.resetStorage = function() {
|
|
localStorage[window.plugin.restoolsBBWatchReloaded.BB_STORAGE] = null;
|
|
}
|
|
|
|
// --- DIALOG
|
|
window.plugin.restoolsBBWatchReloaded.showDialog = function(waves)
|
|
{
|
|
let maxBeaconsWonRes = -Infinity; // Initialize with a very small value
|
|
let maxBeaconsWonEnl = -Infinity;
|
|
let volatilesBeaconsWonResInBestWave = -Infinity; // Initialize with a very small value
|
|
let volatilesBeaconsWonEnlInBestWave = -Infinity;
|
|
|
|
let htmlBegin = `
|
|
<div class="restoolsBBWatchReloadedDialog">
|
|
<table class="styled-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Wave</th>
|
|
<th># of BBs (volatiles)</th>
|
|
<th>% points RES</th>
|
|
<th>% points ENL</th>
|
|
<th># winner RES (volatiles)</th>
|
|
<th># winner ENL (volatiles)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
`;
|
|
|
|
let htmlBody = ``;
|
|
|
|
for (let waveIndex in waves)
|
|
{
|
|
let wave = waves[waveIndex];
|
|
if (wave.BeaconsWonRes > maxBeaconsWonRes) {
|
|
maxBeaconsWonRes = wave.BeaconsWonRes;
|
|
volatilesBeaconsWonResInBestWave = wave.BeaconsWonResVolatiles;
|
|
}
|
|
if (wave.BeaconsWonEnl > maxBeaconsWonEnl) {
|
|
maxBeaconsWonEnl = wave.BeaconsWonEnl;
|
|
volatilesBeaconsWonEnlInBestWave = wave.BeaconsWonEnlVolatiles;
|
|
}
|
|
|
|
htmlBody += `
|
|
<tr>
|
|
<td>`+ wave.WaveNumber +`</td>
|
|
<td>`+ wave.beaconCount + " (" + wave.volatilesCount + ")" + `</td>
|
|
<td>`+ wave.PercentageRes +`</td>
|
|
<td>`+ wave.PercentageEnl +`</td>
|
|
<td>`+ wave.BeaconsWonRes + " (" + wave.BeaconsWonResVolatiles + ")" + `</td>
|
|
<td>`+ wave.BeaconsWonEnl + " (" + wave.BeaconsWonEnlVolatiles + ")" + `</td>
|
|
</tr>
|
|
`;
|
|
}
|
|
|
|
let bestScore = `<p style="font-weight: bold;">BB SCORING ESTIMATE: RES ` + maxBeaconsWonRes/(maxBeaconsWonRes+maxBeaconsWonEnl) + `:` + maxBeaconsWonEnl/(maxBeaconsWonRes+maxBeaconsWonEnl)+ ` ENL</p>`;
|
|
let bestScoreVolatiles = `<p style="font-weight: bold;">BB SCORING ESTIMATE (including volatiles, speculative): RES ` + (maxBeaconsWonRes+ 2*volatilesBeaconsWonResInBestWave)/((maxBeaconsWonRes+ 2*volatilesBeaconsWonResInBestWave)+(maxBeaconsWonEnl+ 2*volatilesBeaconsWonEnlInBestWave)) + `:` + (maxBeaconsWonEnl+ 2*volatilesBeaconsWonEnlInBestWave)/((maxBeaconsWonRes+ 2*volatilesBeaconsWonResInBestWave)+(maxBeaconsWonEnl+ 2*volatilesBeaconsWonEnlInBestWave))+ ` ENL</p>`;
|
|
|
|
let htmlEnd = `
|
|
</tbody>
|
|
</table>` + bestScore + bestScoreVolatiles`
|
|
<a onclick="window.plugin.restoolsBBWatchReloaded.resetStorage()" title="Reset local storage (deletes data saved in your browser, do this prior to anomaly)">Reset local storage</a>
|
|
<a style="float: right;" onclick="window.plugin.restoolsBBWatchReloaded.getCurrentState()" title="Refresh this dialog window">Refresh this window</a>
|
|
</div>
|
|
`;
|
|
let html = htmlBegin + htmlBody + htmlEnd;
|
|
|
|
dialog({
|
|
html: html,
|
|
id: 'restools-bbwatch-reloaded',
|
|
dialogClass: 'ui-dialog-restools-bbwatch-reloaded',
|
|
title: 'ResTools BB Watch Reloaded',
|
|
width: "800px"
|
|
});
|
|
}
|
|
|
|
|
|
// --- SETUP ---
|
|
var setup = function()
|
|
{
|
|
window.plugin.restoolsBBWatchReloaded.setupCSS();
|
|
|
|
// Automatic update
|
|
setTimeout(window.plugin.restoolsBBWatchReloaded.updateCurrentState, 10 * 1000);
|
|
window.plugin.restoolsBBWatchReloaded.WAVE_PORTALS = window.plugin.restoolsBBWatchReloaded.loadStorage();
|
|
console.log("BBWatchReloaded: Loaded previous state");
|
|
|
|
|
|
// Toolbox
|
|
$('#toolbox').append('<a onclick="window.plugin.restoolsBBWatchReloaded.getCurrentState()" title="BB Watch Reloaded">BB Watch Reloaded</a>');
|
|
};
|
|
|
|
|
|
// ##### PLUGIN END #####
|
|
|
|
// Load the hooks
|
|
setup.info = plugin_info;
|
|
if (!window.bootPlugins) window.bootPlugins = [];
|
|
window.bootPlugins.push(setup);
|
|
if (window.iitcLoaded && typeof setup === 'function') setup();
|
|
}
|
|
|
|
// Load the plugin as script
|
|
var script = document.createElement('script');
|
|
var info = {};
|
|
if (typeof GM_info !== 'undefined' && GM_info && GM_info.script)
|
|
{
|
|
info.script = {
|
|
version: GM_info.script.version,
|
|
name: GM_info.script.name,
|
|
description: GM_info.script.description
|
|
};
|
|
}
|
|
script.appendChild(document.createTextNode('('+ wrapper +')('+JSON.stringify(info)+');'));
|
|
(document.body || document.head || document.documentElement).appendChild(script);
|