// ==UserScript==
// @name Better BP rates
// @namespace http://tampermonkey.net/
// @version 0.6
// @description Display more meaningful information in the "Your Bonus Points Rate" page
// @author ryden
// @match https://orpheus.network/bonus.php?action=bprates*
// @icon https://www.google.com/s2/favicons?sz=64&domain=orpheus.network
// @grant none
// ==/UserScript==
/**
* @param {String} HTML representing a single element
* @return {Element}
*/
function htmlToElement(html) {
var template = document.createElement('template');
html = html.trim(); // Never return a text node of whitespace as the result
template.innerHTML = html;
return template.content.firstChild;
}
(function() {
'use strict';
const parseNumber = (x) => +x.replaceAll(',', '');
const formatNumber = (x, precision) => x.toLocaleString('en', { minimumFractionDigits: precision, maximumFractionDigits: precision });
const timeframes = [ 1, 24, 24*7, 24*365.256363004/12, 24*365.256363004 ];
//-----------------------------------------------------------------------------------------
const makeRateUpdater = (row, decimals) => (when) => {
row.fields.each(function(i) { this.innerText = formatNumber(timeframes[i] * row.rates[when], decimals[i]); });
row.fields.gbYear.innerText = formatNumber(row.values.gbYear * row.rates[when] / row.rates[4], decimals[5]);
};
//-----------------------------------------------------------------------------------------
const processHeader = (table) => {
const header = table.find('thead tr.colhead').eq(0);
if (header.length === 0) return;
const body = table.find('tbody tr').eq(0);
if (body.length === 0) return;
header.prepend(htmlToElement(`<td style="text-align: center; width: 1px;">When</td>`));
body.prepend(htmlToElement(`<td style="text-align: center; width: 1px;">
<select id="bp-selector" style="text-align: center">
<option value="0" selected="selected">Now</option>
<option value="1">In a day</option>
<option value="2">In a week</option>
<option value="3">In a month</option>
<option value="4">In a year</option>
</select>
</td>`));
return ({
selector: body.find('#bp-selector'),
});
};
//-----------------------------------------------------------------------------------------
const parseTable = (table) => table
.find('tbody > tr')
.map(function() {
return ({
rateFields: $(this).find('td:gt(3):lt(8)'),
bpGbYearField: $(this).find('td:eq(9)')[0],
});
})
.map(function() {
const fields = this.rateFields;
const values = fields.map(function() { return parseNumber(this.innerText); }).toArray();
const rates = timeframes.map((v, i) => values[i] / v);
return ({
fields: Object.assign(fields, { gbYear: this.bpGbYearField }),
values: Object.assign(values, { gbYear: parseNumber(this.bpGbYearField.innerText) }),
rates,
});
})
.toArray();
//-----------------------------------------------------------------------------------------
const headerTable = $('#content table:first').eq(0);
if (headerTable.length === 0) return;
const header = processHeader(headerTable);
if (!header) return;
const torrentTable = $('#content table:last').eq(0);
if (torrentTable === 0 || torrentTable == headerTable) return;
const updaters = [
{ tbl: headerTable, decimals: [ 2, 2, 2, 2, 2, 2 ] },
{ tbl: torrentTable, decimals: [ 3, 3, 3, 2, 2, 2 ] },
]
.flatMap(({ tbl, decimals }) => parseTable(tbl).map(row => ({ row, decimals })))
.map(({ row, decimals }) => makeRateUpdater(row, decimals));
const update = (n) => updaters.forEach((fn) => fn(n));
header.selector.on('change', function() { update(+this.value); });
update(0);
})();