NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name bots4 Fight Stats
// @version 1.0.1
// @description Displays stats about previous fights while fighting
// @author Clay Banger
// @match https://bots4.net/*
// @grant none
// @require https://kryogenix.org/code/browser/sorttable/sorttable.js
// @license MIT
// @updateURL https://openuserjs.org/meta/Clay_Banger/bots4_Fight_Stats.meta.js
// ==/UserScript==
var $ = window.jQuery;
var WINS=0;
var LOSSES=1;
var TOTAL_DURATION=2;
var TOTAL_EXP=3;
var ENERGY_FIGHTS=4;
var TOTAL_ENERGY=5;
var TOTAL_KUDOS=6;
var OPPONENT_LEVEL=7;
var OPPONENT_COLOUR=8;
var LAST_BATTLED=9;
var OPPONENT_ID=10;
//cosmetic stuff
var BACKGROUND_COLOUR = "#202020";
var BORDER_COLOUR = "#808080";
var TEXT_COLOUR = "#dddddd";
(function() {
'use strict';
//add the link, below HoF to /botsstats
$("#left-nav>ul:first").append("<li><a href='/botsstats'>bots stats</a></li>");
if(document.title == "home - bots4"){
//grab the user/bot information and store
if(!isUserRegistered(getUsername())) {
console.log("Registering user");
linkBotUsername();
}
} else if((document.title == "train - bots4") || (document.title == "fight - bots4")) {
//get the battle length
var battleLength = $("#remaining").html().replace("s","");
//get the current bot we are fighting.
var opponentName = $('#battle-header').html();
//this name isn't stored as neatly as the bots in the fight list, we need to extract it from some HTML.
var start = opponentName.indexOf("vs. ")+4;
var end = opponentName.indexOf("</div>");
var attacker = opponentName.substring(opponentName.indexOf("\">")+2,start-5);
opponentName = opponentName.substring(start,end);
//look up existing data
var fightStats = getStats(attacker, opponentName);
if(fightStats === null) {
//new bot, load up the defaults and information we have already collected
fightStats = new Object();
fightStats.totalFights = 0;
fightStats.avgBattleDur = 0;
fightStats.winPerc = NaN;
fightStats.timeToKEnergy = NaN;
fightStats.avgExp = "-";
fightStats.avgKudos = "-";
fightStats.wins = 0;
fightStats.losses = 0;
fightStats.duration = 0;
fightStats.totalExp = 0;
fightStats.energyFights = 0;
fightStats.totalEnergy = 0;
fightStats.totalKudos = 0;
fightStats.expMin = "-";
}
//add some stats about this fight to the object
fightStats.attacker = attacker;
fightStats.defender = opponentName;
fightStats.battleLength = battleLength;
fightStats.speedBuff = 1;
fightStats.expBuff = 1;
fightStats.kudosBuff = 1;
fightStats.energyBuff = 1;
if (document.title == "fight - bots4") {
fightStats.opponentLevel = window.location.pathname.match(/\/fight\/(\d+)\//)[1];
fightStats.opponentId = window.location.pathname.match(/\/fight\/\d+\/(\d+)\//)[1];
} else if(document.title == "train - bots4") {
fightStats.opponentLevel = lookupTrainBot(parseInt(window.location.pathname.match(/\/train\/(\d+)\//)[1]));
fightStats.opponentId = -1;
}
//get the buffs
$(".buff").not(".buff-inactive").each(function(i) {
//buff is active, we need to modify out battle output accordingly
switch($(this).find("div[style='font-size: 1.5em;']").html()) {
case "Spirit of Wolf I":
fightStats.speedBuff = 1.5;
break;
case "Spirit of Wolf II":
fightStats.speedBuff = 2;
break;
case "Spirit of Wolf III":
fightStats.speedBuff = 2.5;
break;
case "Dark Energy I":
fightStats.energyBuff = 1.5;
break;
case "Dark Energy II":
fightStats.energyBuff = 2;
break;
case "Dark Energy III":
fightStats.energyBuff = 2.5;
break;
case "Mindreave I":
fightStats.expBuff = 0.75;
break;
case "Mindreave II":
fightStats.expBuff = 0.5;
break;
case "Mindreave III":
fightStats.expBuff = 0.25;
break;
case "Kodiac's Endless Intellect I":
fightStats.expBuff = 1.5;
break;
case "Kodiac's Endless Intellect II":
fightStats.expBuff = 2;
break;
case "Kodiac's Endless Intellect II":
fightStats.expBuff = 2.5;
break;
case "Blitz's Bounty I":
fightStats.kudosBuff = 1.5;
break;
case "Blitz's Bounty II":
fightStats.kudosBuff = 2;
break;
case "Blitz's Bounty III":
fightStats.kudosBuff = 2.5;
break;
case "Aura of Eternity":
fightStats.kudosBuff = 2.5;
break;
case "Hastened Adventure":
fightStats.speedBuff = 100;
break;
}
});
//output the stats window
var html = '<div id="botsstats" style="margin: 0 auto 0 auto; ' +
'border: 1px solid ' + BORDER_COLOUR + '; margin-top: 5px; margin-right: 5px; ' +
'font-size: small; background-color: ' + BACKGROUND_COLOUR + ';text-align:left;' +
'color: ' + TEXT_COLOUR + ';right: 0;top: 0;width: 200px;position:fixed;"><p style="margin: 2px 0 1px 0;"> ' +
'<center><u>Fight Stats</u></center><br/>' +
'<table border=0>' +
'<tr><td>Challenger:</td><td>' + attacker + '</td></tr>' +
'<tr><td>Defender:</td><td>' + opponentName + '</td></tr>' +
'<tr><td>Total Fights:</td><td>' + numberWithCommas(fightStats.totalFights) + '</td></tr>' +
'<tr><td>Avg Duration:</td><td>' + fightStats.avgBattleDur + 's</td></tr>' +
'<tr><td>Win %:</td><td>' + fightStats.winPerc + '%</td></tr>';
if (!isNaN(fightStats.timeToKEnergy)) {
html += '<tr><td>1K Energy Time:</td><td>' + fightStats.timeToKEnergy + 's</td></tr>';
}
html += '<tr><td>Avg Exp:</td><td>' + numberWithCommas(fightStats.avgExp) + '</td></tr>'+
'<tr><td>Exp/min:</td><td>' + numberWithCommas(fightStats.expMin) +'</td></tr>' +
'<tr><td>Avg Kudos:</td><td>' + numberWithCommas(fightStats.avgKudos) + '</td></tr>' +
'</table><center><input type="button" id="reset" value="Reset" /></center></p></div>';
$("body").append(html);
//add event listener to reset button
$("#reset").bind( "click", function() {
resetStats(opponentName, attacker);
});
//get stats at the end of the battle
findFinish(fightStats);
} else if(document.title == "train list - bots4") {
//show any stats we have alongside the training bots info
if(!isUserRegistered(getUsername())) {
//no bot name registered with that username, which is weird.
} else {
//find training bot names and look for matches with current logged in botname
$(".box>a:first-child").each(function(i) {
var trainInfo = getStats(getBotname(getUsername()), $(this).html());
if(trainInfo !== null) {
//display found matches alongside training bot info
$(this).parent().append("<table><tr><th>Fights</th><th>Win %</th><th>Avg Dur</th><th>Avg Exp</th><th>Exp/min</th><th>Avg Kudos</th></tr>"+
"<tr><td class='subtext'>"+numberWithCommas(trainInfo.totalFights)+"</td>" +
"<td class='subtext'>"+trainInfo.winPerc+"%</td>" +
"<td class='subtext'>"+trainInfo.avgBattleDur+"s</td>" +
"<td class='subtext'>"+numberWithCommas(trainInfo.avgExp)+"</td>" +
"<td class='subtext'>"+numberWithCommas(trainInfo.expMin)+"</td>" +
"<td class='subtext'>"+numberWithCommas(trainInfo.avgKudos)+"</td></tr></table>");
}
});
}
} else if(document.title == "fight list - bots4") {
//show any stats we have alongside the bots
if(!isUserRegistered(getUsername())) {
//no bot name registered with that username, which is weird.
} else {
//we good.
//find botnames that match any in the list
var botName = getBotname(getUsername());
//cycle through all of the bots listed on the page
$(".botrow").each(function(i) {
//check to see if we have info for the bot
var rowBot = $(this).children().eq(2).html();
var fightStats = getStats(botName, rowBot);
if(fightStats !== null) {
//we have some stored details!
var divName = rowBot.replace(/\ /g,"_");
var html = "<div style='position: relative'><img id='"+divName+"' src='/favicon.ico'/>";
html += "<div id='hidden_"+divName+"' style='position: absolute;display:none;width: 350px;' class='buff-details'><table><tr>"+
"<th class='sorttable_nosort'>Fights</th>"+
"<th class='sorttable_nosort'>Win %</th>"+
"<th class='sorttable_nosort'>Avg Dur</th>";
if (!isNaN(fightStats.timeToKEnergy)) {
html += "<th class='sorttable_nosort'>1k Eng Time</th>";
}
html += "<th class='sorttable_nosort'>Avg Exp</th>"+
"<th class='sorttable_nosort'>Exp/min</th>"+
"<th class='sorttable_nosort'>Avg Kudos</th></tr>" +
"<tr><td>"+numberWithCommas(fightStats.totalFights)+"</td>" +
"<td>"+fightStats.winPerc+"%</td>"+
"<td>"+fightStats.avgBattleDur+"s</td>";
if (!isNaN(fightStats.timeToKEnergy)) {
html += "<td>"+fightStats.timeToKEnergy+"s</td>";
}
html += "<td>"+numberWithCommas(fightStats.avgExp)+"</td>"+
"<td>"+numberWithCommas(fightStats.expMin)+"</td>" +
"<td>"+numberWithCommas(fightStats.avgKudos)+"</td></tr>" +
"</table></div></div>";
$(this).children().eq(11).append(html);
//add mouse listeners
$("#"+divName).mouseover(function(){
$("#hidden_"+this.id).css("display", "block");
});
$("#"+divName).mouseleave(function() {
$("#hidden_"+this.id).css("display", "none");
});
}
});
}
} else if(window.location.href.indexOf("bots4.net/profile/") != -1) {
//check if we have any stats
var fightStats = [];
var botname = $(".block-list:eq(1)>tbody>tr>td:eq(0)>span").html();
for(var j=0, len=localStorage.length; j<len; j++) {
if(localStorage.key(j).match("BOTSSTATS_"+botname+"_") !== null) {
fightStats.push(localStorage.key(j));
}
}
if(fightStats.length !== 0) {
//we have some stats!
var html = "<h2>Fight stats</h2><table><thead><tr>" +
"<th>Challenger</th>" +
"<th>Fights</th>"+
"<th>Win %</th>"+
"<th>Avg Dur</th>"+
"<th>1k Eng Time</th>"+
"<th>Avg Exp</th>"+
"<th>Exp/min</th>"+
"<th>Avg Kudos</th>"+
"<th>Last Battled</th></tr></thead><tbody>";
for(var j=0; j<fightStats.length;j++) {
var challenger = fightStats[j].split("_")[2];
var stats = getStats(challenger ,botname);
var lastBattle = new Date(parseInt(stats.lastBattled));
var ago = days_between(lastBattle, new Date());
var challengerDeets = getChallengerDetails(challenger);
html +="<tr><td>";
if(challengerDeets === undefined) {
html += challenger;
} else {
html += "<a href='/profile/"+challengerDeets.id+"' style='color: "+challengerDeets.colour+";'>"+challenger+"</a>";
}
html += "</td>" +
"<td>"+numberWithCommas(stats.totalFights)+"</td>" +
"<td class='ratio_"+stats.winPercColour+"'>"+stats.winPerc+"%</td>"+
"<td>"+stats.avgBattleDur+"s</td>"+
"<td>"+stats.timeToKEnergy+"s</td>"+
"<td>"+numberWithCommas(stats.avgExp)+"</td>"+
"<td>"+numberWithCommas(stats.expMin)+"</td>"+
"<td style='color:";
console.log(fightStats.avgKudos);
if(parseInt(stats.avgKudos)<0) {
html += "red";
} else {
html += "#0f0";
}
html += "'>"+numberWithCommas(stats.avgKudos)+"</td>" +
"<td >"+lastBattle.toLocaleDateString("en-GB")+"<br><span class='subtext'>[<span class='subsubtext'>";
if(ago === 0) {
html += "today</span>";
} else {
html += ago+" day";
if(ago != 1) {
html += "s";
}
html += "</span> ago";
}
html += "]</span></td></tr>";
}
html += "</tbody></table>";
$("h2:contains('Energy history')").before(html);
}
} else if(window.location.pathname == "/botsstats") {
document.title = "bots stats - bots4";
$("#page-title").html("bots stats");
var html = "<h2>Bot List</h2><table id='bot_list' class='sortable'><thead><tr>"+
"<th class='sorttable_nosort'>botname</th>"+
"<th>level</th>"+
"<th>challenger</th>"+
"<th>total fights</th>"+
"<th>win %</th>"+
"<th>avg duration</th>"+
"<th>1k energy time</th>"+
"<th>avg exp</th>"+
"<th>exp/min</th>"+
"<th>avg kudos</th>"+
"<th>last battled</th>"+
"<th class='sorttable_nosort'></th>"+
"</tr></thead><tbody>";
for(var j=0;j<localStorage.length;j++) {
if(localStorage.key(j).match(/BOTSSTATS_/g) !== null) {
//we have a bot! do some calcs and output it
var keyDeets = localStorage.key(j).split("_");
var fightStats = getStats(keyDeets[2], keyDeets[1]);
var challengerDeets = getChallengerDetails(fightStats.challenger);
var lastBattle = new Date(parseInt(fightStats.lastBattled));
var ago = days_between(lastBattle, new Date());
html += "<tr class='botrow'><td>";
if(parseInt(fightStats.opponentId) == -1) {
//we have a training bot
html += "<a href='/train' style='color: "+fightStats.opponentColour+";'>";
} else {
//regular bot
html += "<a href='/profile/"+fightStats.opponentId+"' style='color: "+fightStats.opponentColour+";'>";
}
html += fightStats.defender+"</a></td>"+
"<td class='subtext' sorttable_customkey='"+fightStats.opponentLevel+"'>[<span class='subsubtext'>"+fightStats.opponentLevel+"</span>]</td>"+
"<td><a href='/profile/"+challengerDeets.id+"' style='color:"+challengerDeets.colour+"' sorttable_customkey='"+challengerDeets.name.toLowerCase()+"'>"+challengerDeets.name+"</a></td>"+
"<td>"+numberWithCommas(fightStats.totalFights)+"</td>" +
"<td sorttable_customkey='"+fightStats.winPerc+"'><span class='ratio_"+fightStats.winPercColour+"'>"+fightStats.winPerc+"%</span></td>" +
"<td>"+fightStats.avgBattleDur+"</td>" +
"<td>"+fightStats.timeToKEnergy+"</td>" +
"<td>"+numberWithCommas(fightStats.avgExp)+"</td>" +
"<td>"+numberWithCommas(fightStats.expMin)+"</td>" +
"<td style='color: ";
if(fightStats.avgKudos<0) {
html += "red";
} else {
html += "#0f0";
}
html += ";'>"+numberWithCommas(fightStats.avgKudos)+"</td>" +
"<td sorttable_customkey='"+fightStats.lastBattled+"'>"+lastBattle.toLocaleDateString("en-GB")+"<br><span class='subtext'>[<span class='subsubtext'>";
if(ago === 0) {
html += "today</span>";
} else {
html += ago+" day";
if(ago != 1) {
html += "s";
}
html += "</span> ago";
}
html += "]</span></td>" +
"<td><input class='delete_button' type='button' value='Delete'/></td></tr>";
}
}
html += "</table>";
html += "<style>table.sortable th:not(.sorttable_sorted):not(.sorttable_sorted_reverse):not(.sorttable_nosort):after {content: ' \\25B4\\25BE' }</style>";
//add import and export buttons
html += "<h2>Export</h2><input type='button' value='Export' id='export'/>"+
"<h2>Import</h2><textarea rows=1 cols=20 id='import_file'></textarea><br/><input type='button' value='Import' id='import'/><span id='import_span'></span>"+
"<h2>Clear</h2><input type='button' value='Clear' id='clear' /><span id='clear_span'></span>";
$("#content").append(html);
//enable buttons
$(".delete_button").each(function(i) {
$(this).bind( "click", function() { removeRow($(this).parents("tr")); });
});
$("#export").bind( "click", function() { exportBotsStats(); });
$("#import").bind( "click", function() { importWarning(); });
$("#clear").bind( "click", function() { clearWarning(); });
}
})();
function resetStats(opponentName, attacker) {
localStorage.removeItem("BOTSSTATS_"+opponentName+"_"+attacker);
$("#botsstats").html("<center>Stats Reset</center>");
}
function getStats(attacker, defender) {
//loads the supplied bot string into an object, returns null if it doesn't exist
var rawStats = localStorage.getItem("BOTSSTATS_"+defender+"_"+attacker);
if(rawStats === null) {
return rawStats
} else {
rawStats = rawStats.split("_");
var calcStats = new Object();
calcStats.wins = parseInt(rawStats[WINS]);
calcStats.losses = parseInt(rawStats[LOSSES]);
calcStats.duration = parseFloat(rawStats[TOTAL_DURATION]);
calcStats.totalExp = parseInt(rawStats[TOTAL_EXP]);
calcStats.energyFights = parseInt(rawStats[ENERGY_FIGHTS]);
calcStats.totalEnergy = parseInt(rawStats[TOTAL_ENERGY]);
calcStats.totalKudos = parseInt(rawStats[TOTAL_KUDOS]);
calcStats.opponentLevel = parseInt(rawStats[OPPONENT_LEVEL]);
calcStats.opponentColour = rawStats[OPPONENT_COLOUR];
calcStats.lastBattled = rawStats[LAST_BATTLED];
calcStats.opponentId = rawStats[OPPONENT_ID];
calcStats.totalFights = calcStats.wins+calcStats.losses;
calcStats.avgBattleDur = (calcStats.duration/parseFloat(calcStats.totalFights)).toFixed(2);
if(calcStats.losses == 0) {
calcStats.winPerc = 100.00;
} else if((calcStats.losses == 0) && (calcStats.wins == 0)) {
calcStats.winPerc = "NaN";
} else {
calcStats.winPerc = ((parseFloat(calcStats.wins)/parseFloat(calcStats.totalFights))*100).toFixed(2);
}
calcStats.winPercColour = Math.round(calcStats.winPerc/6.666);
if(calcStats.winPercColour === 0) {
calcStats.winPercColour = 1;
}
calcStats.timeToKEnergy = Math.round((1000/(parseFloat(calcStats.totalEnergy)/parseFloat(calcStats.energyFights)))*calcStats.avgBattleDur);
calcStats.avgExp = Math.round(parseFloat(calcStats.totalExp)/parseFloat(calcStats.totalFights));
calcStats.expMin = Math.round((60.0/calcStats.avgBattleDur)*calcStats.avgExp);
calcStats.avgKudos = Math.round(calcStats.totalKudos/(calcStats.totalFights));
calcStats.defender = defender;
calcStats.challenger = attacker;
return calcStats;
}
}
function getUsername() {
return $(".box>div>a[href^='/profile']").html();
}
function getBotname(username) {
//returns undefined if the bot hasn't been linked
var botName = localStorage.getItem("BOTSSTATSLINK_"+username);
if(botName === null) {
return undefined;
} else {
return botName.split("_")[0];
}
}
function getChallengerDetails(username) {
var challengerDeets = localStorage["BOTSSTATSLINK_"+username];
if(challengerDeets !== undefined) {
var deets = new Object();
deets.colour = challengerDeets.split("_")[2];
deets.id = challengerDeets.split("_")[1];
deets.name = username;
return deets;
} else {
return undefined;
}
}
function isUserRegistered(username) {
if(getBotname(username) === undefined) {
return false;
} else {
return true;
}
}
function removeRow(row) {
var botname = $(row).find("td:eq(0)>a").html();
var attacker = $(row).find("td:eq(2)>a").html();
localStorage.removeItem("BOTSSTATS_"+botname+"_"+attacker);
$(row).remove();
}
function linkBotUsername() {
$.ajax($(".box>div>a[href^='/profile']").attr("href"), {
success: function(data) {
var user = getUsername();
var bot = data.match(/\<th\>\s*\<div\>Botname:\<\/div\>\s*\<\/th\>\s*\<td\>\<span style=\"color: #\w+;\"\>([^<]+)<\/span\>\<\/td\>/)[1];
var id = data.match(/\<th\>\s*\<div\>Id:\<\/div\>\s*\<\/th\>\s*\<td\>(\d+)\<\/td\>/)[1];
var colour = $(".box>div>a[href^='/profile']").css("color");
localStorage['BOTSSTATSLINK_'+user] = bot+"_"+id+"_"+colour;
localStorage['BOTSSTATSLINK_'+bot] = user+"_"+id+"_"+colour;
console.log("Bot/user linked!");
},
error: function(error) {
console.log(error);
}
});
}
function exportBotsStats() {
var toExport = "";
for(var j=0, len=localStorage.length; j<len; j++) {
if(localStorage.key(j).match(/BOTSSTATS/g) !== null) {
toExport += localStorage.key(j)+"\""+localStorage[localStorage.key(j)]+"\n";
}
}
var today = new Date();
download(toExport, "bots_stats_export_"+today.getFullYear()+"_"+(today.getMonth()+1)+"_"+today.getDate()+".txt", "text/plain;charset=utf-8");
}
function importWarning() {
//check import data
var toImport = $("#import_file").val().split('\n');
if(toImport!="") {
$("#import_file").prop("disabled", true);
var itsOK = 0;
for(var i=0;i<toImport.length;i++) {
var line = toImport[i]
var check1 = line.match(/BOTSSTATS_[^_]+_[^"]+\"(?:-?[\d|.]+_){8}rgb\(\d+,\s*\d+,\s*\d+\)(?:_-?\d+){2}/);
var check2 = line.match(/BOTSSTATSLINK_[^"]+\"[^_]+_\d+_rgb\(\d+,\s*\d+,\s*\d+\)/);
if((check1 === null) && (check2 === null) && (line !== "")) {
//check failed
itsOK = i+1;
i=toImport.length+100;
}
}
if(itsOK===0) {
$("#import_span").html(" <span style='color: red'>WARNING:</span> This will overwrite existing data. Click Import to continue");
$("#import").bind( "click", function() { importBotsStats(); });
} else {
$("#import_span").html("Invalid import data. Issue on line: "+itsOK);
$("#import_file").prop("disabled", false);
}
} else {
$("#import_span").html("No data found");
}
}
function importBotsStats() {
var toImport = $("#import_file").val().split('\n');
for(var i=0;i<toImport.length;i++) {
var line = toImport[i];
//ignores blank lines
if(line !== "") {
line = line.split("\"");
localStorage.setItem(line[0],line[1]);
}
}
$("#import_span").html("Import successful! <input type='button' value='Reload' onClick='window.location.reload()' />");
$("#import").hide();
}
function clearWarning() {
$("#clear_span").html(" <span style='color: red'>WARNING: THIS WILL CLEAR ALL DATA!</span> Make sure you have a backup handy, just in case. Click Clear again to proceed.");
$("#clear").bind( "click", function() { clearStats(); });
}
function clearStats() {
var listToDelete = [];
for(var j=0; j<localStorage.length; j++) {
if(localStorage.key(j).match(/BOTSSTATS/g) !== null) {
listToDelete.push(localStorage.key(j));
}
}
for(var i=0;i<listToDelete.length;i++){
localStorage.removeItem(listToDelete[i]);
}
$("#clear_span").html("Cleared. <input type='button' value='Reload' onClick='window.location.reload()' />");
$("#clear").hide();
}
function findFinish(fightStats) {
if($("#battle-summary").length !== 0) {
//the fight is over
//pull the energy obtained from the battle log.
var battleLog = $("#battle-log").html();
var kudos = "";
var energy = battleLog.match(/is exhausted and (?:loses|gives you) \<span class\=\"subsubtext\">(\d+)\<\/span\> energy./m);
if(energy === null) {
energy = 0;
} else {
energy = energy[1];
fightStats.energyFights++;
}
kudos = battleLog.match(/The B.O.T.S. Union takes \<span class\=\"subsubtext\">([\d|,]+)\<\/span\> kudos/m);
if(kudos === null) {
kudos = battleLog.match(/The B.O.T.S. Union hands you \<span class\=\"subsubtext\">([\d|,]+)\<\/span\> kudos/m)[1];
} else {
kudos = kudos[1];
}
var exp = battleLog.match(/Your bot gains \<span class\=\"subsubtext\">([\d|,]+)\<\/span\> experience points/m)[1];
//we now know how much energy we have. Now figure out who won.
var winner = $("#battle-summary>tbody>tr>td:last>span").html();
var way = "";
if((winner == fightStats.defender) && (document.title != "train - bots4") && (document.title != "(!) train - bots4")) {
//challenger lost
way = "-";
}
var addToWins = 0;
var addToLoss = 0;
if(winner == fightStats.defender) {
addToLoss = 1;
} else {
addToWins = 1;
}
//get the colour of the opponent
var opponentDisplay = $("#battle-summary>tbody>tr>td:eq(5)>span").css("color");
//current time, to serve as last battled time
var lastBattled = (new Date).getTime();
//store
var botInfo = [parseInt(fightStats.wins)+addToWins,
fightStats.losses+addToLoss,
(fightStats.duration+parseFloat(fightStats.battleLength)*fightStats.speedBuff).toFixed(2),
parseFloat(fightStats.totalExp)+parseFloat(exp.replace(/\,/g,""))/fightStats.expBuff,
fightStats.energyFights,
fightStats.totalEnergy+parseInt(way+energy)/fightStats.energyBuff,
fightStats.totalKudos+parseInt(way+kudos.replace(/\,/g,""))/fightStats.kudosBuff,
fightStats.opponentLevel,
opponentDisplay,
lastBattled,
fightStats.opponentId];
localStorage["BOTSSTATS_"+fightStats.defender+"_"+fightStats.attacker] = botInfo.join("_");
} else {
//fight has not ended yet, wait another 0.1 second for the fight to end.
setTimeout(function(){findFinish(fightStats);}, 100);
}
}
function lookupTrainBot(number) {
switch(number) {
case 1: return 1;
case 2: return 1;
case 3: return 7;
case 4: return 10;
case 5: return 20;
case 6: return 30;
case 7: return 45;
case 8: return 60;
case 9: return 75;
case 10: return 90;
case 11: return 105;
case 12: return 115;
case 13: return 125;
case 14: return 140;
case 15: return 160;
case 16: return 180;
case 17: return 200;
case 18: return 220;
case 19: return 240;
case 20: return 260;
case 21: return 280;
case 22: return 300;
case 23: return 325;
case 24: return 350;
case 25: return 375;
case 26: return 400;
case 27: return 450;
case 28: return 500;
case 29: return 550;
case 30: return 600;
case 31: return 750;
case 32: return 1000;
case 33: return 1200;
case 34: return 1500;
case 35: return 1800;
case 36: return 2100;
default: return undefined;
}
}
function days_between(date1, date2) {
var ONE_DAY = 1000 * 60 * 60 * 24;
var date1_ms = date1.getTime();
var date2_ms = date2.getTime();
var difference_ms = Math.abs(date1_ms - date2_ms);
return Math.round(difference_ms/ONE_DAY);
}
//number format function. Only used to format the energy display. Credit for this function goes to mikez302 from StackOverflow.
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
// Function to download data to a file
//from: https://stackoverflow.com/questions/13405129/javascript-create-and-save-file
function download(data, filename, type) {
var file = new Blob([data], {type: type});
if (window.navigator.msSaveOrOpenBlob) { // IE10+
window.navigator.msSaveOrOpenBlob(file, filename);
} else { // Others
var a = document.createElement("a"),
url = URL.createObjectURL(file);
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}
}