// ==UserScript==
// @name Neopets - Bank improvements for Beta
// @namespace np
// @version 2020.12.30
// @description Various improvements to shop till and bank, including a bank interest calculator.
// @author x
// @include http://www.neopets.com/market.phtml?type=till
// @include http://www.neopets.com/bank.phtml*
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
/************************************************************************
* Removed @require jQuery.
* This lets us use $(document).ajaxSuccess without needing unsafeWindow.
* As of 2020-12-25, neopets beta is using jQuery v3.4.1;
* the version number can be checked in console with $().jquery
************************************************************************/
if (!GM_getValue) {
GM_getValue = (key, val) => localStorage[key] || val;
GM_setValue = (key, val) => localStorage[key] = val;
}
if (!GM_getValue("config")) {
let config = {
deposit : 0,
withdraw : 0,
calc_visible : true
};
GM_setValue("config", config);
}
let config = GM_getValue("config");
//-----------------------------------------------------------------------
const url = location.href;
const isBeta = $("[class^='nav-pet-menu-icon']").length > 0;
if (url.includes("bank") && isBeta) {
const np = $("#npanchor").text().replace(/,/g, "");
const bank = $("#txtCurrentBalance1").text().replace(/[^\d]/g, "");
$("#frmDeposit :input[name='amount']").val(config.deposit || np);
$("#frmWithdraw :input[name='amount']").val(config.withdraw || bank);
$("#frmUpgradeAccount :input[name='amount']").val(np);
$("#frmWithdraw").on("submit", function () {
const amtWithdraw = $("#frmWithdraw :input[name='amount']").val();
if (amtWithdraw !== 0 && !amtWithdraw.match(/[^\d]/g)) {
config.withdraw = amtWithdraw;
GM_setValue("config", config);
}
});
$("h2:contains('Interest')").parent().parent().after(`
<!--Bank interest calculator userscript-->
<style>.interest-div {margin: 3px auto;} .interest-number {height: 30px; width:100px; border: 1px solid #58250d; border-radius: 5px; font-family:'MuseoSansRounded700', 'Arial', sans-serif; margin-right:10px;}</style>
<div class="bank-upgrade bank-section-container">
<div id="hide-calculator" class="bank-upgrade-header bank-backing-header bank-backing-t4" title="Click to hide" style="cursor: pointer;">
<h2>Interest Calculator</h2>
</div>
<div class="bank-upgrade-body bank-backing-marble" style="display: ${config.calc_visible ? "" : "none"}">
<div id="interest-calculator">
<table style="width:60%; border-spacing:0; margin-left:auto; margin-right:auto; padding:10px;">
<tbody>
<tr>
<td style="text-align:right;">
<div class="bank-account-level interest-div">
<span class="bank-text-bold">Account Level:</span>
</div>
</td>
<td>
<div class="bank-account-level interest-div">
<select name="account_type" id="interest-account-type" style="width:250px;">
<option value="0.045">Junior Saver (4.5%)</option>
<option value="0.055">Neopian Student (5.5%)</option>
<option value="0.06">Bronze Saver (6.0%)</option>
<option value="0.065">Silver Saver (6.5%)</option>
<option value="0.07">Super Gold Plus (7.0%)</option>
<option value="0.075">Platinum Extra (7.5%)</option>
<option value="0.08">Double Platinum (8.0%)</option>
<option value="0.085">Triple Platinum (8.5%)</option>
<option value="0.09">Diamond Deposit (9.0%)</option>
<option value="0.095">Diamond Deposit Plus (9.5%)</option>
<option value="0.10">Diamond Deposit Gold (10.0%)</option>
<option value="0.105">Millionaire Platinum (10.5%)</option>
<option value="0.11">Millionaire Double Platinum (11.0%)</option>
<option value="0.115">Millionaire Mega-Platinum (11.5%)</option>
<option value="0.12">Neopian Mega-Riches (12.0%)</option>
<option value="0.125" selected>Ultimate Riches! (12.5%)</option>
</select>
</div>
</td>
</tr>
<tr style="height: 38px">
<td style="text-align:right;">
<div class="bank-add-deposit interest-div">
<span class="bank-text-bold bank-adddeposit-text">Battleground boon:</span>
</div>
</td>
<td>
<div class="bank-add-deposit interest-div">
<label for="boon-enabled" class="bank-text-bold">
<input type="checkbox" id="boon-enabled">
(+3%)
</label>
</div>
</td>
</tr>
<tr>
<td style="text-align:right;">
<div class="bank-add-deposit interest-div">
<span class="bank-text-bold bank-adddeposit-text">Daily interest:</span>
</div>
</td>
<td>
<div class="bank-add-deposit interest-div">
<input class="interest-number" type="text" id="daily-interest" size="10" maxlength="6">
<span class="bank-text-bold">NP</span>
</div>
</td>
</tr>
<tr>
<td style="text-align:right;">
<div class="bank-add-deposit interest-div">
<span class="bank-text-bold bank-adddeposit-text">Account balance:</span>
</div>
</td>
<td>
<div class="bank-add-deposit interest-div">
<input class="interest-number" type="text" id="acc-balance" size="10" maxlength="10">
<span class="bank-text-bold">NP</span>
</div>
</td>
</td>
</tr>
</tbody>
</table>
<!--input class="button-default__2020 button-yellow__2020 btn-single__2020" type="submit" style="margin: 3px auto; padding: 2px 5px 7px 5px !important;" value="Calculate"-->
</div>
</div>
</div>
<!--End of userscript-->`);
$("#hide-calculator").on("click", function () {
const $hideArea = $(this).next();
if ($hideArea.is(":visible")) {
$hideArea.hide(200);
config.calc_visible = false;
} else {
$hideArea.show(200);
config.calc_visible = true;
}
GM_setValue("config", config);
});
/********************************************************
* --- Calculator ---
*
* You can type in "k", "m", and "b" to instantly insert
* 3, 6 and 9 zeroes respectively.
*
* Example: type 22.5k to instantly input 22500,
* 35.55m to instantly input 35550000.
*
* Since the maximum amount of NP in the bank right now
* is 2,147,483,647 the feature above will not convert
* bank balance amounts above this limit.
********************************************************/
// Initial values
const interestRate = 0.01 * parseFloat($("#txtAnnualInterestRate").find("b").html());
$("#interest-account-type").val(interestRate.toString());
$("#acc-balance").val(bank);
$("#daily-interest").val(Math.ceil(bank * interestRate / 365));
const validateInput = input => !input.match(/[^\d]+/g);
const validateLength = (input, length) => input.length <= length;
$("#interest-account-type").on("change", function() {
const newInterestRate = parseFloat(this.value);
const bankBal = $("#acc-balance").val();
$("#daily-interest").val(Math.ceil(bankBal * newInterestRate / 365));
});
$("#boon-enabled").on("change", function (e) {
const checked = e.target.checked;
const interestRate = parseFloat($("#interest-account-type").val());
const bankBal = $("#acc-balance").val();
const newDailyInterest = checked ?
Math.ceil(bankBal * (interestRate + 0.03) / 365) :
Math.ceil(bankBal * interestRate / 365);
$("#daily-interest").val(newDailyInterest);
});
$("#daily-interest").on("input", function (e) {
const key = e.originalEvent.data;
let newVal;
if (key === "k") {
newVal = (parseFloat(this.value) * 1000).toString();
this.value = validateLength(newVal, 6) ? newVal : this.value;
}
const daily = this.value;
if (validateInput(daily)) {
const newBal = daily === "" ? "" : Math.floor(daily * 365 / interestRate);
$("#acc-balance").val(newBal);
}
});
$("#acc-balance").on("input", function (e) {
const key = e.originalEvent.data;
let newVal;
if (key === "k") {
newVal = (parseFloat(this.value) * 1000).toString();
this.value = validateLength(newVal, 10) ? newVal : this.value;
}
if (key === "m") {
newVal = (parseFloat(this.value) * 1000000).toString();
this.value = validateLength(newVal, 10) ? newVal : this.value;
}
if (key === "b") {
newVal = (parseFloat(this.value) * 1000000000).toString();
this.value = validateLength(newVal, 10) ? newVal : this.value;
}
const bal = this.value;
if (validateInput(bal)) {
const newDaily = bal === "" ? "" : Math.ceil(bal * interestRate / 365);
$("#daily-interest").val(newDaily);
}
});
/*
<div id="bankInterestDailyWrapper">
<div class="bank-interest-daily">
<div id="txtDailyInterest" class="bank-interest-daily-text bank-text-bold">
Daily Interest: 33,909 NP
</div>
<form action="/np-templates/ajax/process_bank.php" method="post" id="frmCollectInterest" onsubmit="return one_submit();">
<input type="hidden" name="type" value="interest">
<input type="hidden" name="_ref_ck" value="e3d2c0afd96f354377d62ac96d1319a7">
<input class="bank-interest-btn button-default__2020 button-yellow__2020" type="submit" value="Collect Interest">
</form>
</div>
</div>
*/
// prevent input while xhr is sending
$(document).ajaxStart(function () {
$("#interest-account-type").prop("disabled", true);
$("#boon-enabled").prop("disabled", true);
$("#daily-interest").prop("disabled", true);
$("#acc-balance").prop("disabled", true);
});
// Auto-update the calculator values after a deposit/withdrawal or collecting interest.
$(document).ajaxSuccess(function (event, xhr, settings) {
// for collecting interest, the xhr completes before the bank balance is updated,
// so we read the response data instead
try {
const response = JSON.parse(xhr.responseText);
// check that this xhr is related to bank updating
if (response["final_balance"] || response["new_balance"]) {
const updatedBal = parseInt(response["final_balance"]) || response["new_balance"];
const updatedInterestRate = 0.01 * parseFloat($("#txtAnnualInterestRate").find("b").html());
const updatedDaily = Math.ceil(updatedBal * updatedInterestRate / 365);
$("#daily-interest").val(updatedDaily);
$("#acc-balance").val(updatedBal);
}
} catch (e) {
// response probably isn't in JSON format
// ie - not related to bank xhr
}
// re-enable calculator
$("#interest-account-type").prop("disabled", false);
$("#boon-enabled").prop("disabled", false);
$("#daily-interest").prop("disabled", false);
$("#acc-balance").prop("disabled", false);
});
}
/*
if (url.includes("till")) {
const till = $("p:contains('You currently have')").find("b").text().replace(/[^\d]/g, "");
if (till !== "0") {
$("form[action='process_market.phtml']").find("input[name='amount']").val(till);
}
}
*/