Skip to content

Instantly share code, notes, and snippets.

@nabbynz
Last active January 31, 2020 02:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nabbynz/9c3e5de9690483cb2871 to your computer and use it in GitHub Desktop.
Save nabbynz/9c3e5de9690483cb2871 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name STATS OFF Rolling 300 Timeline
// @description Shows a Rolling 300 Timeline & Streaks (using UNOFFICIAL game data) on your chosen server homepage.
// @version 3.0.5
// • 3.0.5: Made compatible with SWJ
// • 3.0.4: Fixed bug (tagpro.serverHost is always null now)
// • Fixed CTF/NF detection
// • Made compatible with new TagPro site design
// • Updated to ChartJS v2
// • Added Get Other Player Id's from the Leaderboards
// @include *://tagpro*.koalabeast.com*
// @updateURL https://gist.github.com/nabbynz/9c3e5de9690483cb2871/raw/STATS_OFF_O300_Timeline.user.js
// @downloadURL https://gist.github.com/nabbynz/9c3e5de9690483cb2871/raw/STATS_OFF_O300_Timeline.user.js
// @require https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.min.js
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_addStyle
// @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
// @author nabby
// ==/UserScript==
console.log('START: ' + GM_info.script.name + ' (v' + GM_info.script.version + ' by ' + GM_info.script.author + ')');
var $uHome = $('#userscript-home');
var $uTop = $('#userscript-top');
var $uBottom = $('#userscript-bottom');
var options = { //defaults
//Best not to edit these ones (you can select them through the on-page menu)...
'O300MainPages': { display:'Home,Profile,Joiner', type:'checkbox', value:0, title:'Home,Profile'},
'O300HeaderPages': { display:'Home,Profile,Joiner,Game', type:'checkbox', value:0, title:'Home,Profile,Joiner,Game'},
'O300HeaderShowNGames': { display:'# Oldest/Newest Games in Header: ', type:'number', value:3, title:'Oldest & Newest'},
'MaxO300Games': { display:'# Games to View: ', type:'overwritten', value:50, title:''},
'ShowO300Timeline': { display:'Show Timeline', type:'checkbox', value:true, title:''},
'ShowO300Intervals': { display:'Show Win % Bands for...', type:'checkbox', value:true, title:''},
'O300WinBands': { display:'20,25,30,50,75,100,150', type:'subradio', value:50, title:''},
'ShowO300WinPercentage': { display:'Show Win %', type:'checkbox', value:true, title:''},
'ShowO300Count': { display:'Show Count', type:'checkbox', value:true, title:''},
'ShowO300HighestLowestEver': { display:'Show Highest/Lowest %\'s (ever)', type:'checkbox', value:true, title:'This will only appear once 300 games have been played'},
'ShowO300CTFNF': { display:'Show CTF/NF Win %\'s', type:'checkbox', value:true, title:''},
'ShowO300OldestGame': { display:'Show "Oldest Game"', type:'checkbox', value:false, title:''},
'ShowO300NextGameAffect': { display:'Show "Next Game" effect', type:'checkbox', value:true, title:''},
'ShowO300MapStats': { display:'Show MapStats', type:'checkbox', value:true, title:''},
'ShowO300ASBP': { display:'Show Average Scoreboard Position', type:'checkbox', value:true, title:''},
'ShowO300GamesPieChart': { display:'Show Pie Chart', type:'checkbox', value:true, title:''},
'ShowO300BestStreak': { display:'Show Best Streak', type:'checkbox', value:true, title:''},
'ShowO300CurrentStreak': { display:'Show Current Streak', type:'checkbox', value:true, title:''},
'ShowO300WinStreakMessage': { display:'Show "Best Streak" Messages', type:'checkbox', value:true, title:'Show messages like: "You are currently on your best win streak!"'},
'ShowO300LossStreakMessage': { display:'Show "Worst Streak" Messages', type:'checkbox', value:false, title:'Show messages like: "You are currently on your worst losing streak"'},
'ShowO300PerDayGraph': { display:'Show # Games Per Day Graph', type:'checkbox', value:true, title:''},
'ShowO300PerDay': { display:'Show # Games Per Day', type:'checkbox', value:true, title:''},
'ShowO300PUPs': { display:'Show Per-Game Stats Table', type:'checkbox', value:true, title:''},
'ShowO300PUPsPerGame': { display:'Show values as "Per-Game"', type:'overwritten', value:true, title:'Click to change between per-game averages & totals'},
'ShowOtherPlayers': { display:'Show Other Players Win%', type:'checkbox', value:true, title:''},
'ShowO300ShowGap': { display:'Show a gap between games in Timeline', type:'checkbox', value:true, title:''},
'ShowBoxShadowBorder': { display:'Show Shadow around Border?', type:'checkbox', value:false, title:''},
'ShowLessThan300GamesWarning': { display:'Show the "Mini Selection" Window', type:'checkbox', value:true, title:''},
'ShowO300TrimmedGamesPieChart': { display:'Show Mini Pie Chart', type:'checkbox', value:true, title:''},
'ShowO300TrimmedPUPs': { display:'Show Power-Up Stats', type:'checkbox', value:true, title:''},
'AlwaysShowLastDayPlayed': { display:'Always Start With Last Day Played', type:'checkbox', value:true, title:''},
//You can manually edit the "value" for these options if you want (but they will revert when the script updates)...
'Win_Color': { display:' Color for a "Win"', type:'manual', value:'#22DD22', title:''},
'Loss_Color': { display:' Color for a "Loss"', type:'manual', value:'#EE2020', title:''},
'DC_Color': { display:' Color for a "DC (Loss)"', type:'manual', value:'#FFFF00', title:''},
'SSA_Color': { display:' Color for a "Successful Save Attempt (Win)"', type:'manual', value:'#166C16', title:''},
'FSA_Color': { display:' Color for a "Unsuccessful Save Attempt"', type:'manual', value:'#157798', title:''},
'Tie_Color': { display:' Color for a "Tie (Loss)"', type:'manual', value:'#ff9900', title:''},
'Unknown_Color': { display:' Color for a "Unknown"', type:'manual', value:'#888888', title:''}, //just in case!
//These are updated by the script...
'O300SavedGames': { type:'script', display:'', value:[] },
};
var O300_Selections; // = options;
var delayLoadingBy = 1000;
$.get('https://i.imgur.com/WKZPcQA.gif'); //preload the ajax loading gif
function secondsToHMS(d) {
d = Number(d);
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.floor(d % 3600 % 60);
return ((h > 0 ? h + ":" : "") + (m > 0 ? (h > 0 && m < 10 ? "0" : "") + m + ":" : "0:") + (s < 10 ? "0" : "") + s);
}
function scaleBetween(unscaledNum, minAllowed, maxAllowed, min, max){
return (maxAllowed-minAllowed) * (unscaledNum-min) / (max-min || 1) + (max-min ? minAllowed : maxAllowed);
}
function capitaliseFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function comparer(index) {
return function(a, b) {
var valA = getCellValue(a, index), valB = getCellValue(b, index);
return $.isNumeric(valA) && $.isNumeric(valB) ? valB - valA : valA.localeCompare(valB);
};
}
function getCellValue(row, index) {
return $(row).children('td').eq(index).data('sortby');
}
/*!
* hoverIntent v1.8.0 // 2014.06.29 // jQuery v1.9.1+
* http://cherne.net/brian/resources/jquery.hoverIntent.html
*
* You may use hoverIntent under the terms of the MIT license. Basically that
* means you are free to use hoverIntent as long as this header is left intact.
* Copyright 2007, 2014 Brian Cherne
*/
(function($){$.fn.hoverIntent=function(handlerIn,handlerOut,selector){var cfg={interval:100,sensitivity:6,timeout:0};if(typeof handlerIn==="object"){cfg=$.extend(cfg,handlerIn)}else{if($.isFunction(handlerOut)){cfg=$.extend(cfg,{over:handlerIn,out:handlerOut,selector:selector})}else{cfg=$.extend(cfg,{over:handlerIn,out:handlerIn,selector:handlerOut})}}var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if(Math.sqrt((pX-cX)*(pX-cX)+(pY-cY)*(pY-cY))<cfg.sensitivity){$(ob).off("mousemove.hoverIntent",track);ob.hoverIntent_s=true;return cfg.over.apply(ob,[ev])}else{pX=cX;pY=cY;ob.hoverIntent_t=setTimeout(function(){compare(ev,ob)},cfg.interval)}};var delay=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);ob.hoverIntent_s=false;return cfg.out.apply(ob,[ev])};var handleHover=function(e){var ev=$.extend({},e);var ob=this;if(ob.hoverIntent_t){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t)}if(e.type==="mouseenter"){pX=ev.pageX;pY=ev.pageY;$(ob).on("mousemove.hoverIntent",track);if(!ob.hoverIntent_s){ob.hoverIntent_t=setTimeout(function(){compare(ev,ob)},cfg.interval)}}else{$(ob).off("mousemove.hoverIntent",track);if(ob.hoverIntent_s){ob.hoverIntent_t=setTimeout(function(){delay(ev,ob)},cfg.timeout)}}};return this.on({"mouseenter.hoverIntent":handleHover,"mouseleave.hoverIntent":handleHover},cfg.selector)}})(jQuery);
var WhichPageAreWeOn = function(){
if (window.location.port || window.location.href.endsWith('/game')) { //In a real game
return('ingame');
} else if (document.URL.indexOf('/games/find') > 0) { //Joining page
return('joining');
} else if ($('#userscript-home').length) { //Chosen server homepage
return('server');
} else if (document.URL.indexOf('/profile/') > 0) {
if ($('#saveSettings').length) {
return('profile'); //Profile page and logged in
} else {
return('profileNotOurs'); //Profile page, but not our one (or we're logged out)
}
} else if (document.URL.indexOf('/groups') > 0) {
return('groups');
} else if (document.URL.indexOf('/boards') > 0) {
return('boards');
} else if (document.URL.indexOf('/maps') > 0) {
return('maps');
} else if (document.URL.indexOf('/settings') > 0) {
return('settings');
}
};
var PageLoc = WhichPageAreWeOn();
function getUsefulText(value, what){
if (what == 'gamemode') {
if (value === 1) {
return 'CTF';
} else if (value === 2) {
return 'Neutral Flag';
} else {
return '';
}
} else if (what == 'outcome') {
if (value === '10') { //value must be passed as a string ('outcome'+'saved')
return 'Win';
} else if (value === '20') {
return 'Loss';
} else if (value === '30') {
return 'DC';
} else if (value === '41') {
return 'Unsuccessful Save Attempt';
} else if (value === '12') {
return 'Successful Save Attempt';
} else if (value === '50') {
return 'Tie';
}
}
}
function getOldestGamesBlock(data, numberGamesToShow) {
if (numberGamesToShow === 0) {
return '';
} else {
numberGamesToShow = numberGamesToShow || 3;
}
if (data.length >= numberGamesToShow) {
var blocks = '<div style="display:inline-block; margin-right:5px">';
for (var i=0; i<(numberGamesToShow); i++) {
if (data[i].outcome === 1) {
if (data[i].saved === 2) {
blocks += '<div class="fl_ssa o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
} else {
blocks += '<div class="fl_win o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
}
} else if (data[i].outcome === 2) {
blocks += '<div class="fl_loss o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
} else if (data[i].outcome === 3) {
blocks += '<div class="fl_dc o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
} else if (data[i].outcome === 4) { //Save Attempt
if (data[i].saved === 1) { //Unsuccessful
blocks += '<div class="fl_fsa o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
}
} else if (data[i].outcome === 5) { //Tie
blocks += '<div class="fl_tie o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
} else { //Unknown
blocks += '<div class="fl_unk o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
}
}
blocks+= '</div>';
return blocks;
} else {
return '';
}
}
function getLatestGamesBlock(data, numberGamesToShow) {
if (numberGamesToShow === 0) {
return '';
} else {
numberGamesToShow = numberGamesToShow || 3;
}
if (data.length >= numberGamesToShow) {
var blocks = '<div style="display:inline-block; margin-left:5px">';
for (var i=data.length-numberGamesToShow; i<data.length; i++) {
if (data[i].outcome === 1) {
if (data[i].saved === 2) {
blocks += '<div class="fl_ssa o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
} else {
blocks += '<div class="fl_win o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
}
} else if (data[i].outcome === 2) {
blocks += '<div class="fl_loss o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
} else if (data[i].outcome === 3) {
blocks += '<div class="fl_dc o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
} else if (data[i].outcome === 4) { //Save Attempt
if (data[i].saved === 1) { //Unsuccessful
blocks += '<div class="fl_fsa o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
}
} else if (data[i].outcome === 5) { //Tie
blocks += '<div class="fl_tie o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
} else { //Unknown
blocks += '<div class="fl_unk o300_game" data-gamenumber="'+(data.length-i)+'"></div>';
}
}
blocks+= '</div>';
return blocks;
} else {
return '';
}
}
function getNextGamePercentage(data) {
var i, wins=0, losses=0;
var IfWin='', IfLose='';
for (i=0; i<data.length; i++) {
if (data[i].outcome == 1) {
wins++;
} else if ((data[i].outcome == 2) || (data[i].outcome == 3) || (data[i].outcome == 5)) {
losses++;
}
}
if (data[0].outcome === 1) {
if (data.length < 300) {
IfWin = ((wins+1) / (wins+1+losses) * 100).toFixed(2);
IfLose = ((wins) / (wins+losses+1) * 100).toFixed(2);
return ('<span style="color:'+O300_Selections.Win_Color.value+'">Win Next:&#42779;'+IfWin + '%</span> | <span style="color:'+O300_Selections.Loss_Color.value+'">Lose Next:&#42780;'+IfLose+'%</span>');
} else if (data.length === 300) {
IfLose = ((wins-1) / (wins-1+losses+1) * 100).toFixed(2);
return ('<span style="color:'+O300_Selections.Win_Color.value+'">Win Next: No effect</span> | <span style="color:'+O300_Selections.Loss_Color.value+'">Lose Next:&#42780;'+IfLose+'%</span>');
}
} else if ((data[0].outcome === 2) || (data[0].outcome == 3)) {
if (data.length < 300) {
IfWin = ((wins+1) / (wins+1+losses) * 100).toFixed(2);
IfLose = ((wins) / (wins+losses+1) * 100).toFixed(2);
return ('<span style="color:'+O300_Selections.Win_Color.value+'">Win Next:&#42779;'+IfWin + '%</span> | <span style="color:'+O300_Selections.Loss_Color.value+'">Lose Next:&#42780;'+IfLose+'%</span>');
} else if (data.length === 300) {
IfWin = ((wins+1) / (wins+1+losses-1) * 100).toFixed(2);
return ('<span style="color:'+O300_Selections.Win_Color.value+'">Win Next:&#42779;'+IfWin + '%</span> | <span style="color:'+O300_Selections.Loss_Color.value+'">Lose Next: No effect</span>');
}
} else if (data[0].outcome === 4) { //Save Attempt
if (data[0].saved === 1) { //Unsuccessful
IfWin = ((wins+1) / (wins+1+losses) * 100).toFixed(2);
IfLose = ((wins) / (wins+losses+1) * 100).toFixed(2);
return ('<span style="color:'+O300_Selections.Win_Color.value+'">Win Next:&#42779;'+IfWin + '%</span> | <span style="color:'+O300_Selections.Loss_Color.value+'">Lose Next:&#42780;'+IfLose+'%</span>');
}
} else if (data[0].outcome === 5) { //Tie
if (data.length < 300) {
IfWin = ((wins+1) / (wins+1+losses) * 100).toFixed(2);
IfLose = ((wins) / (wins+losses+1) * 100).toFixed(2);
return ('<span style="color:'+O300_Selections.Win_Color.value+'">Win Next:&#42779;'+IfWin + '%</span> | <span style="color:'+O300_Selections.Loss_Color.value+'">Lose Next:&#42780;'+IfLose+'%</span>');
} else if (data.length === 300) {
IfWin = ((wins+1) / (wins+1+losses-1) * 100).toFixed(2);
return ('<span style="color:'+O300_Selections.Win_Color.value+'">Win Next:&#42779;'+IfWin + '%</span> | <span style="color:'+O300_Selections.Loss_Color.value+'">Lose Next: No effect</span>');
}
} else {
return '';
}
}
function getWinPercentage(data) {
var i, wins=0, losses=0;
if (data.length) {
for (i=0; i<data.length; i++) {
if (data[i].outcome == 1) {
wins++;
} else if ((data[i].outcome == 2) || (data[i].outcome == 3) || (data[i].outcome == 5)) {
losses++;
}
}
return (wins / (wins+losses) * 100).toFixed(2);
}
}
function getGamesTilNextFlair(data, winP) { //thanks Snaps!
var thresholds = [55, 65, 75];
var threshold;
var outcomes = data.map(function (d) { return d.outcome; });
for (var i = 0; i < thresholds.length; i++) {
if (winP < thresholds[i]) {
threshold = thresholds[i];
break;
}
}
if (!threshold) return false;
function getPct(vals) {
return vals.goods / (vals.goods + vals.bads);
}
var bads = [2, 3, 5];
var vals = outcomes.reduce(function (vals, outcome) {
if (outcome === 1) {
vals.goods++;
} else if (bads.indexOf(outcome) !== -1) {
vals.bads++;
}
return vals;
}, { goods: 0, bads: 0 });
var winsNeeded = 0;
var game = 0;
while (getPct(vals) * 100 < threshold && game < outcomes.length) {
var outcome = outcomes[game];
if (bads.indexOf(outcome) !== -1) {
vals.goods++;
vals.bads--;
} else if (outcome === 4) {
vals.goods++;
}
winsNeeded++;
game++;
}
return {
wins: winsNeeded,
goal: threshold
};
}
function showWinPercentageHeader(data) {
if (data === undefined) data = $.extend(true, [], allGames);
var blocks = "";
// Oldest games...
blocks += '<div style="display:inline-block">'+getOldestGamesBlock(data, O300_Selections.O300HeaderShowNGames.value)+'</div>';
// Current Win %...
var winP = getWinPercentage(data);
blocks += '<div style="display:inline-block">Current: ' + winP + '%&nbsp;|&nbsp;</div>';
// Predicted Win %...
blocks += '<div class="O300_Stats_Dependent" style="display:inline-block; color:#bbb">' + getNextGamePercentage(data) + '</div>';
// # of games to next % flair...
if (data.length === 300) {
var nextFlairInfo = getGamesTilNextFlair(data, winP);
if (nextFlairInfo) {
blocks += '&nbsp;|&nbsp;<div class="O300_Stats_Dependent" style="display:inline-block; color:#bbb">' + nextFlairInfo.wins + ' Wins = ' + nextFlairInfo.goal + '%</div>';
} else {
blocks += '&nbsp;|&nbsp;<div class="O300_Stats_Dependent" style="display:inline-block; color:#bbb">You\'re above 75%!</div>';
}
}
// Most recent games...
blocks += '<div style="display:inline-block">'+getLatestGamesBlock(data, O300_Selections.O300HeaderShowNGames.value)+'</div>';
$('#O300_WinNextHeader').append(blocks);
$('.fl_win').css ({ 'display':'inline-block', 'border-radius':'2px', 'margin-left':'1px' , 'background-color':O300_Selections.Win_Color.value, 'height':'8px', 'width':'8px' });
$('.fl_loss').css({ 'display':'inline-block', 'border-radius':'2px', 'margin-left':'1px' , 'background-color':O300_Selections.Loss_Color.value, 'height':'8px', 'width':'8px' });
$('.fl_dc').css ({ 'display':'inline-block', 'border-radius':'2px', 'margin' :'0 0 2px 1px', 'background-color':O300_Selections.DC_Color.value, 'height':'4px', 'width':'8px' });
$('.fl_ssa').css ({ 'display':'inline-block', 'border-radius':'2px', 'margin-left':'1px' , 'background-color':O300_Selections.SSA_Color.value, 'height':'6px', 'width':'8px', 'border-top' :'2px solid white' });
$('.fl_fsa').css ({ 'display':'inline-block', 'border-radius':'2px', 'margin-left':'1px' , 'background-color':O300_Selections.FSA_Color.value, 'height':'6px', 'width':'8px', 'border-bottom':'2px solid white' });
$('.fl_tie').css ({ 'display':'inline-block', 'border-radius':'2px', 'margin-left':'1px' , 'background-color':O300_Selections.Tie_Color.value, 'height':'8px', 'width':'8px' });
$('.fl_unk').css ({ 'display':'inline-block', 'border-radius':'2px', 'margin-left':'1px' , 'background-color':O300_Selections.Unknown_Color.value, 'height':'8px', 'width':'8px' });
$('#O300_WinNextHeader').find('.o300_game').hoverIntent(function() {
if ($('#O300_GameInfo').parent().attr('id') !== 'O300_WinNextHeader') $('#O300_WinNextHeader').append( $('#O300_GameInfo') );
showGameInfo($(this).data('gamenumber')-1, $(this).position().top+15, $(this).position().left-200);
}, function() {
$('#O300_GameInfo').hide(0);
});
}
var allGames = [];
function loadData() {
var data = $.extend(true, [], O300_Selections.O300SavedGames.value);
if (data.length > 300) {
while (data.length > 300) {
data.shift();
}
O300_Selections.O300SavedGames.value = $.extend(true, [], data);
GM_setValue('O300_Selections', O300_Selections);
}
if (data.length > 0) {
for (var key=0, l=data.length; key<l; key++) {
data[key].gameNumber = (data.length - key);
}
allGames = $.extend(true, [], data);
$('#O300_loading').remove();
if ($('#O300_WinNextHeader').length) {
showWinPercentageHeader(data);
}
if ($('#O300').length) {
$('#O300_Trimmed').show(0);
showData();
showTrimmedData(O300_Selections.MaxO300Games.value, O300_Selections.MaxO300Games.value);
buildMenu();
bindEvents();
setSavedValues();
}
} else {
$('#O300_Settings_Button').hide(0);
$('#O300').empty();
$('#O300').append('No data for STATS OFF Rolling 300 Timeline - go play some games!');
}
GM_addStyle('.O300_CTFNFWP:hover { border-bottom:1px dotted #9264DA }');
}
//Other Players O300 Win Percentages...
function okToRequestServerData() { //we're only allowed to request the data up to 5 times per minute. Try and make sure we don't exceed this limit.
var serverRequests = GM_getValue('serverRequests', []);
var gotCount = 0;
var max = 0;
if (serverRequests.length > 0) {
for (var i=serverRequests.length; i>=0; i--) {
if (serverRequests[i] > Date.now()-60000) gotCount++;
if (serverRequests[i] > max) max = serverRequests[i];
}
}
//console.log('O300 - okToRequestServerData gotCount:'+gotCount);
if (gotCount < 5) {
return ( Date.now() - max ); //true
} else {
return false;
}
}
function showProfiles() {
var profilesData = GM_getValue('profilesData', []);
var sortby = GM_getValue('O300_OtherPlayersStats_Sortby', 'winRate');
var title;
$('#O300_OtherPlayersStats').find('.O300_OtherPlayerStats').remove();
profilesData.sort( function(a, b) {
if (sortby === 'reservedName') {
return a.reservedName.toLowerCase().localeCompare(b.reservedName.toLowerCase());
} else if (sortby === 'bestWinRate') {
return (b.stats.rollingCache.bestWinRate - a.stats.rollingCache.bestWinRate);
} else if (sortby === 'today') {
return (b.games.today - a.games.today);
} else if (sortby === 'week') {
return (b.games.week - a.games.week);
} else if (sortby === 'month') {
return (b.games.month - a.games.month);
} else {
return (b.stats.rollingCache.winRate - a.stats.rollingCache.winRate);
}
});
for (var i=0; i<profilesData.length; i++) {
title = '';
if (profilesData[i].games.today) title += "Today: " + (profilesData[i].won.today / (profilesData[i].games.today - profilesData[i].stats.today.saveAttempts + profilesData[i].stats.today.saved) * 100).toFixed(2) + "% (" + profilesData[i].games.today + " games)";
else title += "Today: No games played";
if (profilesData[i].games.week) title += "\nWeek: " + (profilesData[i].won.week / (profilesData[i].games.week - profilesData[i].stats.week.saveAttempts + profilesData[i].stats.week.saved) * 100).toFixed(2) + "% (" + profilesData[i].games.week + " games)";
else title += "\nWeek: No games played";
if (profilesData[i].games.month) title += "\nMonth: " + (profilesData[i].won.month / (profilesData[i].games.month - profilesData[i].stats.month.saveAttempts + profilesData[i].stats.month.saved) * 100).toFixed(2) + "% (" + profilesData[i].games.month + " games)";
else title += "\nMonth: No games played";
if (profilesData[i].reservedName === null) profilesData[i].reservedName = (profilesData[i]._id).slice(-12); //the reservedName shows as null if the player has not set a reserved name.
$('#O300_OtherPlayersStats').append('<div class="O300_OtherPlayerStats"><a href="/profile/'+profilesData[i]._id+'" target="_blank" class="O300_OtherPlayerName" title="View '+profilesData[i].reservedName+'\'s Profile Page...">'+profilesData[i].reservedName+'</a>' +
'<div><span title="Current Win Rate: ' + (profilesData[i].stats.rollingCache.winRate * 100).toFixed(2) + '%">'+(profilesData[i].stats.rollingCache.winRate * 100).toFixed(2)+'%</span> <span title="Best Win Rate: ' + (profilesData[i].stats.rollingCache.bestWinRate * 100).toFixed(2) + '%">('+(profilesData[i].stats.rollingCache.bestWinRate * 100).toFixed(2)+'%)</span></div>' +
'<div title="'+title+'"><span' + (profilesData[i].games.today ? ' class="O300_OtherPlayer_HighlightToday"' : '') + '>D:'+profilesData[i].games.today+'</span> W:'+profilesData[i].games.week+' M:'+profilesData[i].games.month+'</div><div class="O300_OtherPlayerStats_Remove" data-profileid="'+profilesData[i]._id+'" title="Remove '+profilesData[i].reservedName+'">X</div></div>');
}
$('#O300_OtherPlayersStats_Add_Spin').removeClass('O300_RotateAddText');
}
function getProfilesData(newId) {
var profileIds = GM_getValue('profileIds', []);
if (profileIds.length) {
$.getJSON('/profiles/' + profileIds.join(',')).done(function(profilesData) {
var serverRequests = GM_getValue('serverRequests', []);
serverRequests.push(Date.now());
if (serverRequests.length > 5) serverRequests.shift();
GM_setValue('serverRequests', serverRequests);
if (profilesData.error) {
if (newId) { //we tried to add an id that was bad and is causing an error. since it's already in the saved data we need to try and remove it...
var profilePosition = profileIds.indexOf(newId);
if (profilePosition >= 0) {
profileIds.splice(profilePosition, 1);
GM_setValue('profileIds', profileIds);
}
alert("A server error has occurred: " + profilesData.error + "\n\nPlease try again...\n\n\n");
} else {
var response = confirm("A server error has occured: " + profilesData.error + "\n\nDo you want to delete/reset all the saved ids?\n\n\n\n");
if (response) {
GM_deleteValue('profileIds');
GM_deleteValue('profilesData');
showProfiles();
}
}
} else {
GM_setValue('profilesData', profilesData);
showProfiles();
}
}).fail(function(jqxhr, textStatus, error) {
if (jqxhr.status === 500) {
alert("A server error has occurred: " + jqxhr.status + ' ' + error + "\n\nPlease try again in 1 hour...\n\n\n");
} else {
if (newId) { //we tried to add an id that was bad and is causing an error. since it's already in the saved data we need to try and remove it...
var profilePosition = profileIds.indexOf(newId);
if (profilePosition >= 0) {
profileIds.splice(profilePosition, 1);
GM_setValue('profileIds', profileIds);
}
alert("A server error has occurred: " + jqxhr.status + ' ' + error + "\n\nPlease try again...\n\n\n");
} else {
var response = confirm("A server error has occured: " + jqxhr.status + ' ' + error + "\n\nDo you want to delete/reset all the saved ids?\n\n\n\n");
if (response) {
GM_deleteValue('profileIds');
GM_deleteValue('profilesData');
showProfiles();
}
}
}
});
}
}
function setupStats() {
$('#O300_MessagesPie').after('<div id="O300_OtherPlayersStats"></div>');
if (PageLoc !== 'joining') {
$('#O300_OtherPlayersStats').append('<div id="O300_OtherPlayersStats_Add" title="Add a new player..."><span id="O300_OtherPlayersStats_Add_Spin">&#10133;</span></div>');
$('#O300_OtherPlayersStats').append('<select id="O300_OtherPlayersStats_Sortby">' +
'<option' + (GM_getValue('O300_OtherPlayersStats_Sortby', 'winRate') === 'reservedName' ? ' selected' : '') + ' value="reservedName">Name</option>' +
'<option' + (GM_getValue('O300_OtherPlayersStats_Sortby', 'winRate') === 'winRate' ? ' selected' : '') + ' value="winRate">Current Win%</option>' +
'<option' + (GM_getValue('O300_OtherPlayersStats_Sortby', 'winRate') === 'bestWinRate' ? ' selected' : '') + ' value="bestWinRate">Best Win%</option>' +
'<option' + (GM_getValue('O300_OtherPlayersStats_Sortby', 'winRate') === 'today' ? ' selected' : '') + ' value="today">#Games Today</option>' +
'<option' + (GM_getValue('O300_OtherPlayersStats_Sortby', 'winRate') === 'week' ? ' selected' : '') + ' value="week">#Games Week</option>' +
'<option' + (GM_getValue('O300_OtherPlayersStats_Sortby', 'winRate') === 'month' ? ' selected' : '') + ' value="month">#Games Month</option>' +
'</select>');
$('#O300_OtherPlayersStats').after('<div id="O300_OtherPlayersStats_Add_Container"><div id="O300_AddFromPaste_Tab" class="O300_AddFrom">Paste</div><div id="O300_AddFromLB_Tab" class="O300_AddFrom">Boards</div><div id="O300_AddFromPaste"></div><div id="O300_AddFromLB"></div></div>');
$('#O300_AddFromPaste').append('<div><textarea style="width:261px; height:260px; font-size:11px; background:whitesmoke" placeholder="Paste Profile Id\'s Here\n(e.g.: 519e7e5d6e58644262000052).\n\nSeparate multiple Id\'s with a comma."></textarea></div>');
$('#O300_AddFromLB').append('<div id="O300_AddFromLB_Outer"><table id="O300_AddFromLB_Table"></table></div>');
$('#O300_OtherPlayersStats_Add_Container').append('<div><span id="O300_AddFromLB_Update" class="O300_AddFromLB_Button">Update</span> <span id="O300_AddFromLB_Cancel" class="O300_AddFromLB_Button">Cancel</span></div>');
$('#O300_OtherPlayersStats_Add').on('click', function(e) {
if (okToRequestServerData()) {
if (Date.now() - GM_getValue('lastGotLBs', 0) > 60000) {
$('#O300_OtherPlayersStats_Add_Spin').addClass('O300_RotateAddText');
setTimeout(function() { $('#O300_OtherPlayersStats_Add_Spin').removeClass('O300_RotateAddText'); }, 5000);
$.get('/boards/').done(function(data) {
var profileIds = GM_getValue('profileIds', []);
var boardsProfileIds = [];
var profileId;
var table = [].concat.call($(data).find('#board-Day table tr:gt(0)'), $(data).find('#board-Week table tr:gt(0)'), $(data).find('#board-Month table tr:gt(0)'), $(data).find('#board-Rolling table tr:gt(0)'));
GM_setValue('lastGotLBs', Date.now());
$('#O300_AddFromLB_Table').empty();
$.each(table, function(k, v) {
$.each(v, function(k1, v1) {
profileId = v1.cells[1].children[0].href.slice(-24);
if (boardsProfileIds.indexOf(profileId) === -1) {
boardsProfileIds.push(profileId);
$('#O300_AddFromLB_Table').append('<tr><td><input type="checkbox" name="O300_AddFromLB_Check"'+(profileIds.indexOf(profileId) >= 0 ? ' checked' : '')+'></td><td>'+v1.cells[1].children[0].innerText+'</td><td>'+(v1.cells[1].children[0].href).slice(-24)+'</td></tr>');
}
});
});
GM_setValue('boardsProfileIds', boardsProfileIds);
var rows = $('#O300_AddFromLB_Table tbody tr').get();
rows.sort(function(a, b) {
var A = $(a).children('td').eq(1).text().toLowerCase();
var B = $(b).children('td').eq(1).text().toLowerCase();
if (A < B) return -1;
if (A > B) return 1;
return 0;
});
$.each(rows, function(index, row) {
$('#O300_AddFromLB_Table').children('tbody').append(row);
});
$('#O300_OtherPlayersStats_Add_Spin').removeClass('O300_RotateAddText');
$('#O300_OtherPlayersStats_Add_Container').show(0);
});
} else {
$('#O300_OtherPlayersStats_Add_Container').show(0);
}
} else {
alert("Cannot add new players right now - please try again in 1 minute...\n\n\n");
}
});
$('#O300_AddFromPaste_Tab').on('click', function() {
$('#O300_AddFromPaste').show(0);
$('#O300_AddFromPaste_Tab').css({'color':'black','background':'whitesmoke'});
$('#O300_AddFromLB').hide(0);
$('#O300_AddFromLB_Tab').css({'color':'whitesmoke','background':'#424'});
});
$('#O300_AddFromLB_Tab').on('click', function() {
$('#O300_AddFromLB').show(0);
$('#O300_AddFromLB_Tab').css({'color':'black','background':'whitesmoke'});
$('#O300_AddFromPaste').hide(0);
$('#O300_AddFromPaste_Tab').css({'color':'whitesmoke','background':'#424'});
});
$('#O300_AddFromLB_Update').on('click', function() {
var profileIds = GM_getValue('profileIds', []);
var profileId;
var gtg = false;
if ($('#O300_AddFromLB').is(':visible')) {
var rows = $('#O300_AddFromLB_Table tbody tr').get();
var isSelected, profilePosition;
$.each(rows, function(index, row) {
profileId = $(row).find('td:eq(2)').text();
isSelected = $(row).find('input').is(':checked');
profilePosition = profileIds.indexOf(profileId);
if (isSelected && profilePosition === -1) {
profileIds.push(profileId);
gtg = true;
} else if (!isSelected && profilePosition >= 0) {
profileIds.splice(profilePosition, 1);
gtg = true;
}
});
if (gtg) {
GM_setValue('profileIds', profileIds);
$('#O300_OtherPlayersStats_Add_Spin').addClass('O300_RotateAddText');
getProfilesData(profileId);
setTimeout(function() { $('#O300_OtherPlayersStats_Add_Spin').removeClass('O300_RotateAddText'); }, 5000);
$('#O300_OtherPlayersStats_Add_Container').fadeOut(400);
}
} else if ($('#O300_AddFromPaste').is(':visible')) {
profileId = $('#O300_AddFromPaste').find('textarea').val();
if (profileId) {
//var profileIds = GM_getValue('profileIds', []);
var arrProfileIds = profileId.split(',');
var silentErrors = false;
if (arrProfileIds.length > 1) silentErrors = true;
if (profileIds.length + arrProfileIds.length > 100) {
alert("We can only retrieve 100 ids from the server, and you are requesting " + (profileIds.length + arrProfileIds.length) + " ids\n\nSo " + (profileIds.length + arrProfileIds.length - 100) + " will not be added at this time - sorry!");
arrProfileIds.splice(99 - profileIds.length);
}
for (var i=0; i<arrProfileIds.length; i++) {
profileId = arrProfileIds[i];
profileId = profileId.trim();
if (profileId.length < 24) {
if (silentErrors) console.log('Profile ID Error: The Profile Id should be 24 characters long (' + profileId + ')');
else alert('The Profile Id should be 24 characters long');
continue;
} else if ((profileId.length > 24) && (profileId.indexOf('profile/') >= 0)) {
var pos = profileId.indexOf('profile/') + 8;
profileId = profileId.slice(pos, pos+24);
} else if ((profileId.length > 24) && (profileId.indexOf('/') >= 0)) {
profileId = profileId.slice(-24);
}
if (profileId.length !== 24) {
if (silentErrors) console.log('Profile ID Error: An unknown error has occurred - please try again (' + profileId + ')');
else alert("An unknown error has occurred - please try again...\n\n\n");
continue;
}
if (profileIds.indexOf(profileId) >= 0) {
if (silentErrors) console.log('Profile ID Error: This Profile Id has already been added (' + profileId + ')');
else alert("This Profile Id has already been added\n\n\n");
continue;
} else {
profileIds.push(profileId);
gtg = true;
}
}
if (gtg) {
GM_setValue('profileIds', profileIds);
$('#O300_OtherPlayersStats_Add_Spin').addClass('O300_RotateAddText');
getProfilesData(profileId);
setTimeout(function() { $('#O300_OtherPlayersStats_Add_Spin').removeClass('O300_RotateAddText'); }, 5000); //force stop animation after 5 secs (it will also stop earlier, once data has finished loading)
$('#O300_OtherPlayersStats_Add_Container').fadeOut(400);
GM_setValue('lastGotLBs', 0);
}
}
}
});
$('#O300_AddFromLB_Cancel').on('click', function() {
$('#O300_OtherPlayersStats_Add_Container').fadeOut(400);
});
$('#O300_AddFromPaste_Tab').trigger('click');
GM_addStyle('#O300_OtherPlayersStats_Add_Container { display:none; position:absolute; top:20px; left:50%; padding:10px 20px; font-size:11px; color:#000; text-shadow:none; background:#424; border:2px solid whitesmoke; border-radius:5px; }');
GM_addStyle('.O300_AddFrom { display:inline-block; width:122px; color:#000; font-weight:bold; text-shadow:none; padding:5px; border:1px solid #888; border-radius:5px 5px 0 0; cursor:pointer }');
GM_addStyle('#O300_AddFromLB_Outer { height:260px; padding-right:4px; overflow-y:auto; overflow-x:hidden; }');
GM_addStyle('#O300_AddFromLB_Table { margin:0 auto; font-size:10px; background:whitesmoke; text-align:center; border-collapse:collapse; border:1px solid whitesmoke; }');
GM_addStyle('#O300_AddFromLB_Table td { border:1px solid grey; padding:1px 2px }');
GM_addStyle('#O300_AddFromLB_Table th { border:1px solid grey; padding:1px 2px; font-size:11px; color:#ddd; background:#666 }');
GM_addStyle('.O300_AddFromLB_Button { display:inline-block; color:whitesmoke; font-size:12px; margin:10px 20px; padding:5px 20px; cursor:pointer; border:1px solid whitesmoke; border-radius:4px; }');
GM_addStyle('.O300_AddFromLB_Button:hover { background:rgba(100,255,100,0.5) }');
GM_addStyle('#O300_AddFromLB_Outer::-webkit-scrollbar { width:5px }');
GM_addStyle('#O300_AddFromLB_Outer::-webkit-scrollbar-thumb { background:mediumvioletred; border-radius:2px; }');
GM_addStyle('#O300_AddFromLB_Outer::-webkit-scrollbar-track { background:#ddd; border-radius:2px; }');
$('#O300_OtherPlayersStats_Sortby').on('change', function() {
GM_setValue('O300_OtherPlayersStats_Sortby', this.value);
showProfiles();
});
$('#O300_OtherPlayersStats').on('click', '.O300_OtherPlayerStats_Remove', function(e) {
e.preventDefault();
e.stopPropagation();
var profileIds = GM_getValue('profileIds', []);
var profileId = $(this).data('profileid');
var profilePosition = profileIds.indexOf(profileId);
if (profilePosition >= 0) {
profileIds.splice(profilePosition, 1);
GM_setValue('profileIds', profileIds);
$(this).parent().remove();
var profilesData = GM_getValue('profilesData', []);
for (var i=0; i<profilesData.length; i++) {
if (profilesData[i]._id === profileId) {
profilesData.splice(i, 1); //remove the cached data too
GM_setValue('profilesData', profilesData);
break;
}
}
}
GM_setValue('lastGotLBs', 0);
});
}
}
function buildMenu() {
//Build the settings menu...
$('#O300_Settings_Button').after('<div id="O300_Settings_Menu" style="display:none; position:absolute; right:0; width:300px; margin:-75px -50px 0 0; padding:10px 10px 15px; font-size:11px; text-align:left; background:linear-gradient(#3A8C66, #00a); border-radius:8px; box-shadow:0px 0px 8px #fff; z-index:6000"></div>');
$('#O300_Settings_Menu').append('<div style="margin:0 auto; padding-bottom:5px; font-size:16px; font-weight:bold; color:#000; text-align:center; text-shadow:2px 1px 2px #aaa;">Stats OFF O300 Options</div>');
var pages = [];
$.each(O300_Selections, function(key, value) {
if (value.type === 'checkbox') {
if (key === 'ShowO300Intervals') {
if (allGames.length === 300) { //Only show the bands if there's 300 games available...
$('#O300_Settings_Menu').append('<li style="list-style:none" title="' + value.title + '"><label><input type="checkbox" id="' + key + '" class="'+ value.type + '" ' + (value.value === true ? 'checked' : '') + '>' + value.display + '</label></li>');
$('#O300_Settings_Menu').append('<div id="O300WinBands" style="margin-left:18px; font-size:11px"></div>');
var intBands = (O300_Selections.O300WinBands.display).split(',');
$.each(intBands, function(k,v) {
$('#O300WinBands').append('<label style="margin-left:4px" title="# games"><input type="radio" name="intBand" data-band="'+v+'" ' + (v == O300_Selections.O300WinBands.value ? 'checked' : '') + ' style="margin:3px 1px 3px 3px">'+v+'</label>');
});
}
} else if (key === 'O300MainPages') {
$('#O300_Settings_Menu').append('<div id="O300MainPages" style="text-align:center; font-size:11px">Main Window:</div>');
pages = (O300_Selections.O300MainPages.display).split(',');
$.each(pages, function(k,v) {
$('#O300MainPages').append('<label style="margin-left:4px"><input type="checkbox" name="mainPage" data-page="'+v+'" ' + ((O300_Selections.O300MainPages.title).indexOf(v) >= 0 ? 'checked' : '') + ' style="margin:3px 1px 3px 3px">'+v+'</label>');
});
} else if (key === 'O300HeaderPages') {
$('#O300_Settings_Menu').append('<div id="O300HeaderPages" style="margin-bottom:5px; text-align:center; font-size:11px">Win % Header:</div>');
pages = (O300_Selections.O300HeaderPages.display).split(',');
$.each(pages, function(k,v) {
$('#O300HeaderPages').append('<label style="margin-left:4px"><input type="checkbox" name="headerPage" data-page="'+v+'" ' + ((O300_Selections.O300HeaderPages.title).indexOf(v) >= 0 ? 'checked' : '') + ' style="margin:3px 1px 3px 3px">'+v+'</label>');
});
$('#O300_Settings_Menu').append('<li style="list-style:none; text-align:center" title="' + O300_Selections.O300HeaderShowNGames.title + '"><label>' + O300_Selections.O300HeaderShowNGames.display + '</label><input type="number" id="O300HeaderShowNGames" min="0" max="10" value="'+O300_Selections.O300HeaderShowNGames.value+'" style="width:30px; font-size:11px; text-align:right"></li>');
} else if (key === 'ShowLessThan300GamesWarning') { //this is the start of the "mini-window" options
$('#O300_Settings_Menu').append('<li style="list-style:none; margin-top:10px">Mini-Window Options...</li>');
$('#O300_Settings_Menu').append('<li style="list-style:none" title="' + value.title + '"><label><input type="checkbox" id="' + key + '" class="'+ value.type + '" ' + (value.value === true ? 'checked' : '') + '>' + value.display + '</label></li>');
} else if (key === 'ShowO300HighestLowestEver') {
$('#O300_Settings_Menu').append('<li style="list-style:none" title="' + value.title + '"><label><input type="checkbox" id="' + key + '" class="'+ value.type + '" ' + (value.value === true ? 'checked' : '') + '>' + value.display + '</label>' +
'<div id="O300ClearHighestLowestEver" style="display:inline-block; margin:0 5px; font-size:7px; border:1px solid #099; cursor:pointer" title="Clear/Reset the saved high/low values">CLEAR</div></li>');
} else {
$('#O300_Settings_Menu').append('<li style="list-style:none" title="' + value.title + '"><label><input type="checkbox" id="' + key + '" class="'+ value.type + '" ' + (value.value === true ? 'checked' : '') + '>' + value.display + '</label></li>');
}
}
});
$('#O300_Settings_Menu').append('<div id="pagereloadneeded" style="display:none; margin-left:30px; color:wheat; font-style:italic;">Page Reload Needed...</div>');
$('#O300_Settings_Menu').append('<div style="position:absolute; bottom:2px; right:5px; text-align:right"><a href="https://gist.github.com/nabbynz/23a54cace27ad097d671" target="_blank" style="font-size:11px; color:#888" title="Version: ' + GM_info.script.version + '. Click to manually check for updates (script will auto-update if enabled)...">v' + GM_info.script.version + '</a</div>');
GM_addStyle('#O300_Settings_Menu input { display:inline-block; margin:2px 0 0; color:black; }');
GM_addStyle('#O300_Settings_Menu label { margin-bottom:3px; font-weight:normal; }');
}
function setSavedValues() {
//update with the user saved values...
$.each(O300_Selections, function(key, value) {
if (key === 'O300MainPages') {
if (PageLoc === 'server') {
if (O300_Selections[key].title.indexOf('Home') < 0) {
$('#O300_InnerContainer').hide(0);
} else {
$('#O300_InnerContainer').fadeIn(1200);
}
} else if ((PageLoc === 'profile') || (PageLoc === 'profileNotOurs')) {
if (O300_Selections[key].title.indexOf('Profile') < 0) {
$('#O300').hide(0);
} else {
$('#O300_InnerContainer').show(0);
}
} else if (PageLoc === 'joining') {
if (O300_Selections[key].title.indexOf('Joiner') < 0) {
$('#O300').hide(0);
} else {
$('#O300_InnerContainer').show(0);
}
}
} else if (key == 'ShowO300PUPsPerGame') {
if (value.value === true) {
$('#O300T_PUPs').find('.O300_pups_pergame').show(0);
$('#O300T_PUPs').find('.O300_pups_total').hide(0);
} else {
$('#O300T_PUPs').find('.O300_pups_pergame').hide(0);
$('#O300T_PUPs').find('.O300_pups_total').show(0);
}
} else if (key === 'ShowBoxShadowBorder') {
if (value.value === true) {
$('#O300').css('box-shadow', '#fff 0px 0px 10px');
} else {
$('#O300').css('box-shadow', 'none');
}
} else if (value.type === 'checkbox') {
//Hide certain elements according to the saved values...
if (value.value === false) {
if (key == 'ShowO300Timeline') {
$O300_Timeline.hide(0);
} else if (key === 'ShowO300Intervals') {
$('#O300_Intervals').hide(0);
$('#O300WinBands').find('input').prop('disabled', true);
} else if (key === 'ShowO300GamesPieChart') {
$('#O300_Pie').hide(0);
} else if (key === 'ShowO300WinPercentage') {
$('#O300_Wins').hide(0);
} else if (key === 'ShowO300PerDay') {
$('#O300_GamesPerDay').hide(0);
} else if (key === 'ShowO300PerDayGraph') {
$('#O300_GamesPerDayGraph').hide(0);
} else if (key === 'ShowO300Count') {
$('#O300_Count').hide(0);
} else if (key === 'ShowO300HighestLowestEver') {
$('#O300_HighestLowestEver').hide(0);
} else if (key === 'ShowO300CTFNF') {
$('#O300_CTFNF').hide(0);
} else if (key === 'ShowO300NextGameAffect') {
$('#O300_NextGameAffectWin, #O300_NextGameAffectLose').hide(0);
} else if (key === 'ShowO300MapStats') {
$('#O300_MS').hide(0);
} else if (key === 'ShowO300ASBP') {
$('#O300_ASBP, #O300T_ASBP').hide(0);
} else if (key === 'ShowO300OldestGame') {
$('#O300_OldestGame').hide(0);
} else if (key === 'ShowO300BestStreak') {
$('#O300_BestStreak').hide(0);
} else if (key === 'ShowO300CurrentStreak') {
$('#O300_CurrentStreak').hide(0);
} else if (key === 'ShowO300WinStreakMessage') {
$('#O300_BestStreakMessage').hide(0);
} else if (key === 'ShowO300LossStreakMessage') {
$('#O300_WorstStreakMessage').hide(0);
} else if (key === 'ShowO300PUPs') {
$('#O300_Stats').hide(0);
} else if (key === 'ShowLessThan300GamesWarning') {
$('#O300_Trimmed').hide(0);
$('#ShowO300TrimmedGamesPieChart').prop('disabled', true);
}
}
}
});
}
function bindEvents() {
$('#O300_Settings_Button').on('click', function() {
$('#O300_Settings_Menu').slideToggle(400);
});
$("#O300_Settings_Menu").mouseleave(function() {
$('#O300_Settings_Menu').fadeOut(100);
});
$('#O300WinBands').find('input').on('click', function() {
O300_Selections.O300WinBands.value = $(this).data('band');
GM_setValue('O300_Selections', O300_Selections);
showData();
if (O300_Selections.ShowLessThan300GamesWarning.value) showTrimmedData(O300_Selections.MaxO300Games.value, O300_Selections.MaxO300Games.value);
});
$('#O300MainPages').find('input').on('click', function() {
var newSelection = '';
$.each($('#O300MainPages').find('input'), function() {
if ($(this).is(':checked')) newSelection += $(this).data('page') + ",";
});
O300_Selections.O300MainPages.title = newSelection;
GM_setValue('O300_Selections', O300_Selections);
if (($(this).data('page') === 'Home') && (PageLoc === 'server')) {
$('#O300_InnerContainer').slideToggle(600);
} else if (($(this).data('page') === 'Profile') && ((PageLoc === 'profile') || (PageLoc === 'profileNotOurs'))) {
$('#O300').slideToggle(600);
}
});
$('#O300HeaderPages').find('input').on('click', function() {
var newSelection = '';
$.each($('#O300HeaderPages input'), function() {
if ($(this).is(':checked')) newSelection += $(this).data('page') + ",";
});
O300_Selections.O300HeaderPages.title = newSelection;
GM_setValue('O300_Selections', O300_Selections);
if (($(this).data('page') === 'Home') && (PageLoc === 'server')) {
if ($('#O300_WinNextHeader').length) {
$('#O300_WinNextHeader').slideToggle(400);
} else {
$('body').prepend(WinP_Div);
$('#O300_WinNextHeader').hide(0);
showWinPercentageHeader();
$('#O300_WinNextHeader').slideDown(400);
}
} else if (($(this).data('page') === 'Profile') && ((PageLoc === 'profile') || (PageLoc === 'profileNotOurs'))) {
if ($('#O300_WinNextHeader').length) {
$('#O300_WinNextHeader').slideToggle(400);
} else {
$('body').prepend(WinP_Div);
$('#O300_WinNextHeader').hide(0);
showWinPercentageHeader();
$('#O300_WinNextHeader').slideDown(400);
}
}
});
$('#O300HeaderShowNGames').on('change', function() {
O300_Selections.O300HeaderShowNGames.value = parseInt(this.value);
GM_setValue('O300_Selections', O300_Selections);
$('#O300_WinNextHeader').remove();
$('body').prepend(WinP_Div);
showWinPercentageHeader();
});
$('#O300_Settings_Menu').find('.checkbox').on('click', function() {
O300_Selections[$(this).attr('id')].value = $(this).is(':checked');
GM_setValue('O300_Selections', O300_Selections);
if ($(this).attr('id') == 'ShowO300Timeline') {
$O300_Timeline.fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300Intervals') {
$('#O300_Intervals').fadeToggle(400);
$('#O300WinBands').find('input').prop('disabled', ($(this).prop('checked') ? false : true));
} else if ($(this).attr('id') == 'ShowO300GamesPieChart') {
$('#O300_Pie').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300Pages') {
$('#O300_WinNextHeader').fadeToggle(400);
$('#O300HeaderPages').find('input').prop('disabled', ($(this).prop('checked') ? false : true));
} else if ($(this).attr('id') == 'ShowO300WinPercentage') {
$('#O300_Wins').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300PerDay') {
$('#O300_GamesPerDay').fadeToggle(400);
if ($(this).is(':checked')) {
$(this).parent().after( $('#pagereloadneeded') );
$('#pagereloadneeded').hide(0).fadeIn(400);
} else {
$('#pagereloadneeded').hide(0);
}
} else if ($(this).attr('id') == 'ShowO300PerDayGraph') {
$('#O300_GamesPerDayGraph').fadeToggle(400);
if ($(this).is(':checked')) {
$(this).parent().after( $('#pagereloadneeded') );
$('#pagereloadneeded').hide(0).fadeIn(400);
} else {
$('#pagereloadneeded').hide(0);
}
} else if ($(this).attr('id') == 'ShowO300Count') {
$('#O300_Count').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300HighestLowestEver') {
$('#O300_HighestLowestEver').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300CTFNF') {
$('#O300_CTFNF').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300NextGameAffect') {
$('#O300_NextGameAffectWin, #O300_NextGameAffectLose').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300MapStats') {
$('#O300_MS').fadeToggle(400);
$('#O300_MS_Data').fadeOut(0);
if ($(this).is(':checked')) {
$(this).parent().parent().after( $('#pagereloadneeded') );
$('#pagereloadneeded').hide(0).fadeIn(400);
} else {
$('#pagereloadneeded').hide(0);
}
} else if ($(this).attr('id') == 'ShowO300ASBP') {
$('#O300_ASBP, #O300T_ASBP').fadeToggle(400);
$('#O300_ASBP_Data').fadeOut(0);
if ($(this).is(':checked')) {
$(this).parent().after( $('#pagereloadneeded') );
$('#pagereloadneeded').hide(0).fadeIn(400);
} else {
$('#pagereloadneeded').hide(0);
}
} else if ($(this).attr('id') == 'ShowO300OldestGame') {
$('#O300_OldestGame').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300BestStreak') {
$('#O300_BestStreak').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300CurrentStreak') {
$('#O300_CurrentStreak').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300WinStreakMessage') {
$('#O300_BestStreakMessage').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300LossStreakMessage') {
$('#O300_WorstStreakMessage').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300PUPs') {
$('#O300_Stats').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300TrimmedPUPs') {
$('#O300T_PUPs').fadeToggle(400);
} else if ($(this).attr('id') == 'ShowO300PUPsPerGame') {
$('#O300T_PUPs').find('.O300_pups_pergame').toggle(0);
$('#O300T_PUPs').find('.O300_pups_total').toggle(0);
} else if ($(this).attr('id') == 'ShowOtherPlayers') {
if ($(this).is(':checked')) {
if (okToRequestServerData()) {
setupStats();
if (okToRequestServerData() > 30000) {
getProfilesData(); //only 'get' the data from the server if we haven't done so recently
} else {
showProfiles(); //otherwise use a cached copy
}
} else {
alert("Server not ready - please try again in 1 minute...\n\n\n");
}
} else {
$('#O300_OtherPlayersStats').remove();
}
} else if ($(this).attr('id') == 'ShowO300ShowGap') {
if ($('#O300_OtherPlayersStats').is(':visible')) $('#O300_OtherPlayersStats').remove();
showData();
if (O300_Selections.ShowLessThan300GamesWarning.value) showTrimmedData(O300_Selections.MaxO300Games.value, O300_Selections.MaxO300Games.value);
setSavedValues();
} else if ($(this).attr('id') == 'ShowLessThan300GamesWarning') { //Not a warning anymore - just an on/off toggle for the mini window
$('#O300_Trimmed').fadeToggle(400);
$('#ShowO300TrimmedGamesPieChart').prop('disabled', ($(this).prop('checked') ? false : true));
$('#ShowO300TrimmedPUPs').prop('disabled', ($(this).prop('checked') ? false : true));
$('#AlwaysShowLastDayPlayed').prop('disabled', ($(this).prop('checked') ? false : true));
if (O300_Selections.ShowLessThan300GamesWarning.value) {
setTimelineCellHeights(Cell_Width);
showTrimmedData(O300_Selections.MaxO300Games.value, O300_Selections.MaxO300Games.value);
}
} else if ($(this).attr('id') == 'ShowO300TrimmedGamesPieChart') {
if (O300_Selections.ShowLessThan300GamesWarning.value) showTrimmedData(O300_Selections.MaxO300Games.value, O300_Selections.MaxO300Games.value);
} else if ($(this).attr('id') == 'ShowBoxShadowBorder') {
if ($(this).is(':checked')) {
$('#O300').css('box-shadow', '#fff 0px 0px 10px');
} else {
$('#O300').css('box-shadow', 'none');
}
}
});
$('#O300ClearHighestLowestEver').on('click', function() {
var response = confirm("Your current highest/lowest saved values will be cleared.\n\nOK to continue?");
if (response) {
GM_deleteValue('O300_HighestEver');
GM_deleteValue('O300_LowestEver');
showData();
setSavedValues();
}
});
}
function setTimelineCellHeights(Cell_Width) {
Cell_Width = Cell_Width || 1;
$('#O300_Timeline').find('.o300_win').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'cursor':'pointer', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? 1 : 0)+'px', 'background-color':O300_Selections.Win_Color.value, 'height':'10px', 'width':Cell_Width+'px' });
$('#O300_Timeline').find('.o300_loss').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'cursor':'pointer', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? 1 : 0)+'px', 'background-color':O300_Selections.Loss_Color.value, 'height':'10px', 'width':Cell_Width+'px' });
$('#O300_Timeline').find('.o300_dc').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'cursor':'pointer', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? 1 : 0)+'px', 'background-color':O300_Selections.DC_Color.value, 'height':'10px', 'width':Cell_Width+'px' });
$('#O300_Timeline').find('.o300_ssa').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'cursor':'pointer', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? 1 : 0)+'px', 'background-color':O300_Selections.SSA_Color.value, 'height':'10px', 'width':Cell_Width+'px', 'border-top':'3px solid white' });
$('#O300_Timeline').find('.o300_fsa').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'cursor':'pointer', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? 1 : 0)+'px', 'background-color':O300_Selections.FSA_Color.value, 'height':'10px', 'width':Cell_Width+'px', 'border-bottom':'3px solid white' });
$('#O300_Timeline').find('.o300_tie').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'cursor':'pointer', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? 1 : 0)+'px', 'background-color':O300_Selections.Tie_Color.value, 'height':'10px', 'width':Cell_Width+'px' });
$('#O300_Timeline').find('.o300_unknown').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'cursor':'pointer', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? 1 : 0)+'px', 'background-color':O300_Selections.Unknown_Color.value, 'height':'10px', 'width':Cell_Width+'px' });
}
function showGameInfo(gameNumber, top, left) {
if (!top || top === undefined) top = 0;
if (!left || left === undefined) left = 0;
var game = allGames[allGames.length - gameNumber - 1];
var text = '';
var scoreText = '';
var scoreText2 = '';
if (game.hasOwnProperty('redScore')) {
scoreText = ' (' + game.redScore + ':' + game.blueScore + ')';
if (game.redScore > game.blueScore) {
scoreText2 = '<div class="' + (game.team === 1 ? 'O300_RedTeamColor' : 'O300_BlueTeamColor') + '">' + (game.team === 1 ? 'We (Red) Won!' : 'We (Blue) Lost :(') + '</div>';
} else if (game.redScore < game.blueScore) {
scoreText2 = '<div class="' + (game.team === 1 ? 'O300_RedTeamColor' : 'O300_BlueTeamColor') + '">' + (game.team === 1 ? 'We (Red) Lost :(' : 'We (Blue) Won!') + '</div>';
} else if (game.redScore === game.blueScore) {
scoreText2 = '<div style="color:'+O300_Selections.Tie_Color.value+'">Tied - ' + (game.team === 1 ? 'We were on Red' : 'We were on Blue') + '</div>';
}
}
if (game.outcome === 1) {
if (game.saved === 2) {
text += '<div style="font-weight:bold; color:'+O300_Selections.Win_Color.value+'">Game #' + game.gameNumber + ': Win - Successful Save Attempt!' + scoreText + '</div>';
} else {
text += '<div style="font-weight:bold; color:'+O300_Selections.Win_Color.value+'">Game #' + game.gameNumber + ': Win' + scoreText + '</div>';
}
} else if (game.outcome === 2) {
text += '<div style="font-weight:bold; color:'+O300_Selections.Loss_Color.value+'">Game #' + game.gameNumber + ': Loss' + scoreText + '</div>';
} else if (game.outcome === 3) {
text += '<div style="font-weight:bold; color:'+O300_Selections.DC_Color.value+'">Game #' + game.gameNumber + ': DC/Loss' + scoreText + '</div>';
} else if (game.outcome === 4) { //Save Attempt
if (game.saved === 1) { //Unsuccessful
text += '<div style="font-weight:bold; color:'+O300_Selections.FSA_Color.value+'">Game #' + game.gameNumber + ': Unsuccessful Save Attempt' + scoreText + '</div>';
}
} else if (game.outcome === 5) { //Tie
text += '<div style="font-weight:bold; color:'+O300_Selections.Tie_Color.value+'">Game #' + game.gameNumber + ': Tie/Loss' + scoreText + '</div>';
} else { //Unknown
text += '<div>Unknown Result!</div>';
}
var playedFor = (game.timePlayed / game.fullGameLength * 100).toFixed(2);
if (playedFor >= 100) playedFor = 100;
text += '<div style="font-weight:bold">' + game.mapName + ' by ' + game.mapAuthor + ' (' + getUsefulText(game.gameMode, 'gamemode') + ')</div>' +
'<div>' + new Date(parseInt(Date.parse(game.played))).toLocaleTimeString() + ' (' + new Date(parseInt(Date.parse(game.played))).toDateString() + (game.serverName ? ') on ' + game.serverName : ')') + '</div>' +
'<div style="font-style:italic">You played for ' + secondsToHMS(game.timePlayed) + ' ('+ playedFor + '%)</div>';
if (game.hasOwnProperty('playersData')) {
text += '<table id="O300_GameInfoScoreboard" style="margin:5px 0"><tr><td></td><td>Score</td><td>Tags</td><td>Pops</td><td>Grabs</td><td>Drops</td><td>Hold</td><td>Caps</td><td>Prevent</td><td>Returns</td><td>Support</td><td>PUPs</td><td>Points</td></tr>';
$.each(game.playersData, function(key, value) {
text += '<tr'+(value.us === true ? ' class="O300_GameInfo_HighlightSelf"' : '')+'>' +
'<td class="'+(value.team === 1 ? 'O300_RedTeamColor' : 'O300_BlueTeamColor')+'">'+(value.auth ? '<span style="color:lime">✔</span>' : '')+value.name+'</td>' +
'<td data-raw="'+value.score+'">'+value.score+'</td>' +
'<td data-raw="'+value.tags+'">'+value.tags+'</td>' +
'<td data-raw="'+value.pops+'">'+value.pops+'</td>' +
'<td data-raw="'+value.grabs+'">'+value.grabs+'</td>' +
'<td data-raw="'+value.drops+'">'+value.drops+'</td>' +
'<td data-raw="'+value.hold+'">'+secondsToHMS(value.hold)+'</td>' +
'<td data-raw="'+value.captures+'">'+value.captures+'</td>' +
'<td data-raw="'+value.prevent+'">'+secondsToHMS(value.prevent)+'</td>' +
'<td data-raw="'+value.returns+'">'+value.returns+'</td>' +
'<td data-raw="'+value.support+'">'+value.support+'</td>' +
'<td data-raw="'+value.powerups+'">'+value.powerups+'/'+game.potentialPowerups+'</td>' +
'<td data-raw="'+value.points+'">'+(value.points ? value.points : '-')+'</td>' +
'</tr>';
});
text += '</table>';
} else {
text += '<table style="margin:5px 0"><tr><td>Score</td><td>Tags</td><td>Pops</td><td>Grabs</td><td>Drops</td><td>Hold</td><td>Caps</td> <td>Prevent</td><td>Returns</td><td>Support</td><td>PUPs</td><td>Points</td></tr>' +
'<tr><td>'+game.tags+'</td><td>'+game.score+'</td><td>'+game.pops+'</td><td>'+game.grabs+'</td><td>'+game.drops+'</td><td>'+secondsToHMS(game.hold)+'</td><td>'+game.captures+'</td><td>'+secondsToHMS(game.prevent)+'</td><td>'+game.returns+'</td><td>'+game.support+'</td><td>'+game.powerups+'/'+game.potentialPowerups+'</td><td>'+(game.points ? game.points : '-')+'</td></tr></table>';
}
if (scoreText2) text += scoreText2;
setTimeout(function() {
var $table = $('#O300_GameInfoScoreboard'), $column, prevMax;
for (var i=2; i<=13; i++) {
$column = $('#O300_GameInfoScoreboard tr:gt(0) td:nth-child('+i+')');
prevMax = 0;
$($column).each(function(k, v) {
if ($(this).data('raw') > prevMax) {
$($column).removeClass('O300_Max');
$(this).addClass('O300_Max');
prevMax = $(this).data('raw');
} else if ($(this).data('raw') === prevMax) {
$(this).addClass('O300_Max');
}
});
}
}, 100);
$('#O300_GameInfo').html(text).css({top:top, left:left});
$('#O300_GameInfo').show(0);
}
//the following are id's on http://unfortunate-maps.jukejuice.com and used for map previews
var knownMaps = {
"45" : 363,
"Angry Pig" : 4924,
"Apparition" : 49153,
"Arena" : 4925,
"Atomic" : 29505,
"Backdoor" : 4919,
"Battery" : 381,
"Bigmouth" : 42880,
"Big Vird" : 4921,
"Birch" : 20686,
"Blast Off" : 366,
"Blooper" : 25376,
"Bombing Run" : 367,
"Boombox" : 368,
"Boostsv2.1" : 369,
"Bulldog" : 8445,
"Cedar" : 38002,
"Center Flag" : 4891,
"CFB" : 4931,
"Citadel" : 16395,
"Command Center" : 3,
"Constriction" : 4915,
"Cloud" : 777,
"Clutch" : 4892,
"Colors" : 370,
"Curb" : 29060,
"Danger Zone 3" : 371,
"Dealer" : 29549,
"Del" : 25502,
"DZ4" : 11158,
"Draft" : 6060,
"Dumbbell" : 4893,
"El Moustachio" : 41873,
"EMERALD" : 5436,
"Fiend" : 15557,
"Figure 8" : 4895,
"Flame" : 2668,
"Floral Mappe" : 52017,
"Foozball" : 4934,
"Frontdoor" : 5439,
"GamePad" : 372,
"Gatekeeper" : 2842,
"GeoKoala" : 4898,
"Glory Hole" : 376,
"Goldie" : 51954,
"Grail of Speed" : 4916,
"Graphite" : 17754,
"Gumbo" : 33389,
"Hexane" : 19894,
"Hornswoggle" : 5493,
"Hotspot" : 28092,
"Hurricane" : 4922,
"Hyper Reactor" : 374,
"Hyperdrive" : 4914,
"Hub" : 9200,
"IRON" : 170,
"Jagged" : 4935,
"Kite" : 5619,
"Lights" : 28884,
"Lold" : 4907,
"Market" : 33642,
"Mars Ball Explorer" : 117,
"Mild High" : 40262,
"Mode 7" : 24663,
"Micro" : 4929,
"Monarch" : 252,
"Oval" : 375,
"Phenochilus" : 23432,
"Pilot" : 690,
"Plasma" : 22708,
"Platypus" : 8446,
"Prime" : 29632,
"Reflex2" : 4911,
"Renegade" : 5481,
"Ricochet" : 4920,
"Rink" : 4926,
"RocketBalls" : 4912,
"Rush" : 12265,
"Saigon" : 17656,
"Scorpio" : 21712,
"Sediment" : 16365,
"Shine" : 5426,
"Simplicity" : 377,
"Smirk" : 4913,
"SNES v2" : 4938,
"Solstice" : 32095,
"Speedway" : 4904,
"Spiders" : 4930,
"Star" : 378,
"SuperDuperStamp" : 5328,
"Swoop" : 379,
"Tehuitzingo" : 38047,
"The Holy See" : 373,
"Thinking With Portals" : 6070,
"Tombolo" : 17622,
"Transilio" : 9015,
"Ultradrive" : 6008,
"Vee" : 365,
"Velocity" : 4923,
"Volt" : 4918,
"Wamble" : 31046,
"Whirlwind 2" : 898,
"Wombo Combo" : 10135,
"Wormy" : 1167
};
function updateMapStats(data, totals) {
var showAs = GM_getValue('O300_MS_ShowAs', 'game');
var mapStats = $.extend(true, {}, data);
var divisor = 1;
var fixed = 1;
var mapPreviewID = '';
$('#O300_MS_Totals').empty();
$('#O300_MS_Data_Table tbody').empty();
if (showAs === 'total') {
divisor = 1;
fixed = 0;
} else if (showAs === 'game') {
divisor = totals.totalPlayed;
} else if (showAs === 'minute') {
divisor = totals.mystats.timePlayed / 60;
fixed = 2;
}
$('#O300_MS_Totals').append('<td class="O300_MS_90">'+totals.mapsCount+'</td>' +
'<td class="O300_MS_60">' + //W:'+totals.all.win+' L:'+totals.all.loss+' S:'+totals.all.ssa+' U:'+totals.all.fsa+' T:'+totals.all.tie+
'<div style="display:flex; width:100%; height:8px; overflow:hidden">' +
' <span style="width:'+(totals.all.win/totals.totalPlayed*100).toFixed(2)+'%; height:9px; background:'+O300_Selections.Win_Color.value+'" title="Wins: '+totals.all.win+ '"></span>' +
' <span style="width:'+(totals.all.ssa/totals.totalPlayed*100).toFixed(2)+'%; height:9px; background:'+O300_Selections.SSA_Color.value+'" title="Successful Saves: '+totals.all.ssa+ '"></span>' +
' <span style="width:'+(totals.all.loss/totals.totalPlayed*100).toFixed(2)+'%; height:9px; background:'+O300_Selections.Loss_Color.value+'" title="Losses: '+totals.all.loss+ '"></span>' +
' <span style="width:'+(totals.all.fsa/totals.totalPlayed*100).toFixed(2)+'%; height:9px; background:'+O300_Selections.FSA_Color.value+'" title="Unsuccessful Saves: '+totals.all.fsa+ '"></span>' +
' <span style="width:'+(totals.all.tie/totals.totalPlayed*100).toFixed(2)+'%; height:9px; background:'+O300_Selections.Tie_Color.value+'" title="Ties: '+totals.all.tie+ '"></span>' +
'</div></td>' +
'<td class="O300_MS_60">'+(showAs === 'total' ? totals.totalPlayed : (totals.totalPlayed / totals.mapsCount).toFixed(fixed))+'</td>' +
'<td class="O300_MS_50">'+secondsToHMS(showAs === 'total' ? totals.mystats.timePlayed : totals.mystats.timePlayed / totals.totalPlayed)+'</td>' +
'<td class="O300_MS_50">'+((totals.all.win + totals.all.ssa) / (totals.totalPlayed - totals.all.fsa) * 100).toFixed(2)+'%</td>' +
'<td class="O300_MS_35">'+(totals.SBP / totals.totalPlayed).toFixed(1)+'</td>' +
'<td class="O300_MS_35">'+(totals.mystats.tags / divisor).toFixed(fixed)+'</td>' +
'<td class="O300_MS_35">'+(totals.mystats.pops / divisor).toFixed(fixed)+'</td>' +
'<td class="O300_MS_35">'+(totals.mystats.grabs / divisor).toFixed(fixed)+'</td>' +
'<td class="O300_MS_35">'+(totals.mystats.drops / divisor).toFixed(fixed)+'</td>' +
'<td class="O300_MS_35">'+secondsToHMS(totals.mystats.hold / divisor)+'</td>' +
'<td class="O300_MS_35">'+(totals.mystats.captures / divisor).toFixed(fixed)+'</td>' +
'<td class="O300_MS_35">'+secondsToHMS(totals.mystats.prevent / divisor)+'</td>' +
'<td class="O300_MS_35">'+(totals.mystats.returns / divisor).toFixed(fixed)+'</td>' +
'<td class="O300_MS_35">'+(totals.mystats.support / divisor).toFixed(fixed)+'</td>' +
'<td class="O300_MS_35">'+(totals.mystats.powerups / divisor).toFixed(fixed)+'</td>');
for (var map in mapStats) {
mapPreviewID = '';
if (knownMaps.hasOwnProperty(map)) mapPreviewID = knownMaps[map];
if (showAs === 'total') {
mapStats[map].timePlayed = secondsToHMS(data[map].timePlayed);
} else if (showAs === 'game') {
divisor = mapStats[map].playedCount;
mapStats[map].timePlayed = secondsToHMS(data[map].timePlayed / data[map].playedCount);
} else if (showAs === 'minute') {
divisor = mapStats[map].timePlayed / 60;
mapStats[map].timePlayed = secondsToHMS(data[map].timePlayed / data[map].playedCount);
}
mapStats[map].tags = (data[map].tags / divisor).toFixed(fixed);
mapStats[map].pops = (data[map].pops / divisor).toFixed(fixed);
mapStats[map].grabs = (data[map].grabs / divisor).toFixed(fixed);
mapStats[map].drops = (data[map].drops / divisor).toFixed(fixed);
mapStats[map].hold = secondsToHMS(data[map].hold / divisor);
mapStats[map].captures = (data[map].captures / divisor).toFixed(fixed);
mapStats[map].prevent = secondsToHMS(data[map].prevent / divisor);
mapStats[map].returns = (data[map].returns / divisor).toFixed(fixed);
mapStats[map].support = (data[map].support / divisor).toFixed(fixed);
mapStats[map].powerups = (data[map].powerups / divisor).toFixed(fixed);
$('#O300_MS_Data_Table tbody').append('<tr>' +
'<td class="O300_MS_90 O300_MS_MapName" data-sortby="'+map+'"' + (mapPreviewID ? ' data-previewid="'+mapPreviewID+'" data-mapauthor="'+mapStats[map].mapAuthor+'"' : '') + ' title="Show Map Image">'+(mapStats[map].gameMode === 2 ? '<span title="Neutral Flag">*</span>' : '')+map+'</td>' +
'<td class="O300_MS_60 O300_MS_MapResults" data-sortby="'+mapStats[map].win+'" title="Show All '+map+' Games in Mini-Timeline">' +
'<div style="display:flex; width:'+(mapStats[map].playedCount/totals.highestPlayed*100).toFixed(2)+'%; height:8px; overflow:hidden">' +
' <span style="width:'+(mapStats[map].win/mapStats[map].playedCount*100).toFixed(2)+'%; height:9px; background:'+O300_Selections.Win_Color.value+'" title="Wins: '+mapStats[map].win+ '"></span>' +
' <span style="width:'+(mapStats[map].ssa/mapStats[map].playedCount*100).toFixed(2)+'%; height:9px; background:'+O300_Selections.SSA_Color.value+'" title="Successful Saves: '+mapStats[map].ssa+ '"></span>' +
' <span style="width:'+(mapStats[map].loss/mapStats[map].playedCount*100).toFixed(2)+'%; height:9px; background:'+O300_Selections.Loss_Color.value+'" title="Losses: '+mapStats[map].loss+ '"></span>' +
' <span style="width:'+(mapStats[map].fsa/mapStats[map].playedCount*100).toFixed(2)+'%; height:9px; background:'+O300_Selections.FSA_Color.value+'" title="Unsuccessful Saves: '+mapStats[map].fsa+ '"></span>' +
' <span style="width:'+(mapStats[map].tie/mapStats[map].playedCount*100).toFixed(2)+'%; height:9px; background:'+O300_Selections.Tie_Color.value+'" title="Ties: '+mapStats[map].tie+ '"></span>' +
'</div></td>' +
'<td class="O300_MS_60" data-sortby="'+mapStats[map].playedCount+'">' + (mapStats[map].playedCount/totals.totalPlayed*100).toFixed(2) + '% ('+mapStats[map].playedCount+')</td>' +
'<td class="O300_MS_50" data-sortby="'+data[map].timePlayed+'">' + mapStats[map].timePlayed+'</td>' +
'<td class="O300_MS_50" data-sortby="'+((mapStats[map].win + mapStats[map].ssa) / mapStats[map].playedCount * 100)+'">' + ((mapStats[map].win + mapStats[map].ssa) / mapStats[map].playedCount * 100).toFixed(2) + '%</td>' +
'<td class="O300_MS_35" data-sortby="'+(mapStats[map].SBP / mapStats[map].playedCount).toFixed(1)+'">' + (mapStats[map].SBP / mapStats[map].playedCount).toFixed(1) + '</td>' +
'<td class="O300_MS_35" data-sortby="'+mapStats[map].tags+'">' + mapStats[map].tags + '</td>' +
'<td class="O300_MS_35" data-sortby="'+mapStats[map].pops+'">' + mapStats[map].pops + '</td>' +
'<td class="O300_MS_35" data-sortby="'+mapStats[map].grabs+'">' + mapStats[map].grabs + '</td>' +
'<td class="O300_MS_35" data-sortby="'+mapStats[map].drops+'">' + mapStats[map].drops + '</td>' +
'<td class="O300_MS_35" data-sortby="'+data[map].hold+'">' + mapStats[map].hold + '</td>' +
'<td class="O300_MS_35" data-sortby="'+mapStats[map].captures+'">' + mapStats[map].captures + '</td>' +
'<td class="O300_MS_35" data-sortby="'+data[map].prevent+'">' + mapStats[map].prevent + '</td>' +
'<td class="O300_MS_35" data-sortby="'+mapStats[map].returns+'">' + mapStats[map].returns + '</td>' +
'<td class="O300_MS_35" data-sortby="'+mapStats[map].support+'">' + mapStats[map].support + '</td>' +
'<td class="O300_MS_35" data-sortby="'+mapStats[map].powerups+'">' + mapStats[map].powerups + '</td>' +
'</tr>');
}
//sort the table by last saved...
$('#O300_MS_Data_Table').find('th:eq('+GM_getValue('O300_MS_SortBy', 1)+')').trigger('click', true);
}
/************************************************************************************/
// Main Rolling 300 Timeline & Streaks...
/************************************************************************************/
function showData() {
var Timeline_MaxWidth = 780;
var Cell_Width = 10; //This value will adjust (smaller) according to MaxGames & Timeline_MaxWidth. Default=10
var i, j;
var data = $.extend(true, [], allGames);
var totals = {'all': { win:0, loss:0, dc:0, ssa:0, fsa:0, tie:0 },
'ctf': { win:0, loss:0, dc:0, ssa:0, fsa:0, tie:0 },
'nf': { win:0, loss:0, dc:0, ssa:0, fsa:0, tie:0 },
'mystats': { tags:0, pops:0, grabs:0, drops:0, hold:0, captures:0, prevent:0, returns:0, support:0, powerups:0, timePlayed:0 },
'allstats': { tags:0, pops:0, grabs:0, drops:0, hold:0, captures:0, prevent:0, returns:0, support:0, powerups:0, timePlayed:0, count:0 },
'streaks': { win:0, loss:0, temp_win:0, temp_loss:0, last_win:0, last_loss:0 }
};
var New_Cell_Width = Math.floor((Timeline_MaxWidth - 26) / data.length);
if (New_Cell_Width < Cell_Width) Cell_Width = New_Cell_Width - (O300_Selections.ShowO300ShowGap.value ? 1 : 0);
if (Cell_Width <= 0) Cell_Width = 1;
$('#O300_Intervals').empty();
$O300_Timeline.empty();
$O300_Messages.empty();
$('#O300_Pie').remove();
$('#O300_Stats').remove();
var mapStats = {};
var highestPlayedMapName = '';
var SBPR = {};
var SBP_Us_Total=0, SBP_Us_Count=0, SBP_Length=0;
var totalPotentialPowerups = 0;
var NF_Marker = '<div title="Neutral Flag Game" style="position:absolute; width:'+Cell_Width+'px; height:1px; bottom:-2px; background:#ccc"></div>';
var dayCounts = [];
var dayCountsKey = 0;
var d1 = '';
var d2 = '';
if (O300_Selections.ShowO300MapStats.value) {
totals.totalPlayed = data.length;
totals.mapsCount = 0;
totals.highestPlayed = 0;
totals.SBP = 0;
}
$.each(data, function(key, value) {
if (O300_Selections.ShowO300PerDayGraph.value || O300_Selections.ShowO300PerDay.value) {
d1 = new Date(value.played);
if (key === 0) { //first game, nothing to compare to yet so just push it
dayCounts.push( { day:d1.toDateString(), firstGameNumber:key, win:0, loss:0, dc:0, ssa:0, fsa:0, tie:0, timePlayed:0 } );
} else {
j = Math.ceil((d1 - d2) / (1000 * 3600 * 24));
if ( (d2 !== '') && (d1.toDateString() !== d2.toDateString()) ) {
for (i=dayCountsKey+1; i<dayCountsKey+j; i++) {
dayCounts.push( { day:0, firstGameNumber:0, win:0, loss:0, dc:0, ssa:0, fsa:0, tie:0, timePlayed:0 } ); //push 0's for the in-between days we haven't played on (this could get big?!?)
}
dayCounts.push( { day:d1.toDateString(), firstGameNumber:key, win:0, loss:0, dc:0, ssa:0, fsa:0, tie:0, timePlayed:0 } );
dayCountsKey += j;
}
}
d2 = d1; //save for compare on next loop
dayCounts[dayCountsKey].timePlayed += value.timePlayed;
}
if (O300_Selections.ShowO300MapStats.value) {
if (!mapStats.hasOwnProperty(value.mapName)) { //first time
mapStats[value.mapName] = {};
mapStats[value.mapName].playedCount = 0;
mapStats[value.mapName].timePlayed = 0;
mapStats[value.mapName].mapAuthor = value.mapAuthor;
mapStats[value.mapName].gameMode = value.gameMode;
mapStats[value.mapName].win = 0;
mapStats[value.mapName].loss = 0;
mapStats[value.mapName].tie = 0;
mapStats[value.mapName].ssa = 0;
mapStats[value.mapName].fsa = 0;
mapStats[value.mapName].SBP = 0; //scoreboard position
mapStats[value.mapName].tags = 0;
mapStats[value.mapName].pops = 0;
mapStats[value.mapName].grabs = 0;
mapStats[value.mapName].drops = 0;
mapStats[value.mapName].hold = 0;
mapStats[value.mapName].captures = 0;
mapStats[value.mapName].prevent = 0;
mapStats[value.mapName].returns = 0;
mapStats[value.mapName].support = 0;
mapStats[value.mapName].powerups = 0;
totals.mapsCount++;
}
mapStats[value.mapName].playedCount++;
mapStats[value.mapName].timePlayed += value.timePlayed;
mapStats[value.mapName].tags += value.tags;
mapStats[value.mapName].pops += value.pops;
mapStats[value.mapName].grabs += value.grabs;
mapStats[value.mapName].drops += value.drops;
mapStats[value.mapName].hold += value.hold;
mapStats[value.mapName].captures += value.captures;
mapStats[value.mapName].prevent += value.prevent;
mapStats[value.mapName].returns += value.returns;
mapStats[value.mapName].support += value.support;
mapStats[value.mapName].powerups += value.powerups;
if (mapStats[value.mapName].playedCount > totals.highestPlayed) {
highestPlayedMapName = value.mapName;
totals.highestPlayed = mapStats[value.mapName].playedCount;
}
}
totalPotentialPowerups += value.potentialPowerups;
$.each(totals.mystats, function(key1, value1) {
totals.mystats[key1] += value[key1];
});
if (value.hasOwnProperty('playersData')) {
$.each(value.playersData, function(key1, value1) {
if (O300_Selections.ShowO300MapStats.value) {
if (value1.us) {
mapStats[value.mapName].SBP += key1+1;
totals.SBP += key1+1;
}
}
if (O300_Selections.ShowO300ASBP.value) {
if (value1.us || value1.auth) { //always save us. only save others if authenticated
if (value1.us) value1.name = '♥'; //just a special name for us that nobody will ever use in a game.
SBP_Length++;
if (!SBPR.hasOwnProperty(value1.name)) { //first time
SBPR[value1.name] = {};
SBPR[value1.name].playedCount = 0;
SBPR[value1.name].positions = {1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0};
SBPR[value1.name].us = false;
}
SBPR[value1.name].playedCount++;
SBPR[value1.name].positions[key1+1]++;
if (value1.us) {
SBPR[value1.name].us = true;
SBP_Us_Total += key1+1;
SBP_Us_Count++;
}
}
}
//if (O300_Selections.ShowO300PUPs.value) {
if (value1.tags + value1.pops + value1.grabs + (value1.captures*10) + value1.prevent + value1.support > 10) { //exclude lowly players (probably very late joiners)
totals.allstats.tags += value1.tags;
totals.allstats.pops += value1.pops;
totals.allstats.grabs += value1.grabs;
totals.allstats.drops += value1.drops;
totals.allstats.hold += value1.hold;
totals.allstats.captures += value1.captures;
totals.allstats.prevent += value1.prevent;
totals.allstats.returns += value1.returns;
totals.allstats.support += value1.support;
totals.allstats.powerups += value1.powerups;
totals.allstats.score += value1.score;
totals.allstats.points += value1.points;
totals.allstats.count++;
} else {
//console.log('Player joined late? Game #:'+key + ' (not counting): '+value1.name);
}
//}
});
}
switch (value.outcome) {
case 1: //win
if (value.saved === 2) {
totals.all.ssa++;
if (O300_Selections.ShowO300PerDayGraph.value || O300_Selections.ShowO300PerDay.value) dayCounts[dayCountsKey].ssa++;
if (O300_Selections.ShowO300MapStats.value) mapStats[value.mapName].ssa++;
if (value.gameMode === 1) {
totals.ctf.ssa++;
} else if (value.gameMode === 2) {
totals.nf.ssa++;
}
$O300_Timeline.append('<div class="o300_ssa o300_game" data-gamenumber="' + (data.length-key) + '">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
} else {
totals.all.win++;
if (O300_Selections.ShowO300PerDayGraph.value || O300_Selections.ShowO300PerDay.value) dayCounts[dayCountsKey].win++;
if (O300_Selections.ShowO300MapStats.value) mapStats[value.mapName].win++;
if (value.gameMode === 1) {
totals.ctf.win++;
} else if (value.gameMode === 2) {
totals.nf.win++;
}
$O300_Timeline.append('<div class="o300_win o300_game" data-gamenumber="' + (data.length-key) + '">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
}
//streak...
i=key;
while ( (i > 0) && ((data[i-1].outcome === 4)&&(data[i-1].saved === 1)) ) { //unsuccessful saves shouldn't break a streak!
i--;
}
if ( (totals.streaks.temp_win === 0) || ((i > 0) && ((data[i-1].outcome === 1)) ) ) totals.streaks.temp_win++;
if (totals.streaks.temp_win > totals.streaks.win) totals.streaks.win = totals.streaks.temp_win;
totals.streaks.temp_loss = 0;
if (totals.streaks.temp_win > 0) totals.streaks.last_win = totals.streaks.temp_win;
break;
case 2: //loss
totals.all.loss++;
if (O300_Selections.ShowO300PerDayGraph.value || O300_Selections.ShowO300PerDay.value) dayCounts[dayCountsKey].loss++;
if (O300_Selections.ShowO300MapStats.value) mapStats[value.mapName].loss++;
if (value.gameMode === 1) {
totals.ctf.loss++;
} else if (value.gameMode === 2) {
totals.nf.loss++;
}
$O300_Timeline.append('<div class="o300_loss o300_game" data-gamenumber="' + (data.length-key) + '">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
//streak...
i=key;
while ( (i > 0) && ((data[i-1].outcome === 4)&&(data[i-1].saved === 1)) ) {
i--;
}
if ( (totals.streaks.temp_loss === 0) || ((i > 0) && ((data[i-1].outcome === 2) || (data[i-1].outcome === 3) || (data[i-1].outcome === 5)) ) ) totals.streaks.temp_loss++;
if (totals.streaks.temp_loss > totals.streaks.loss) totals.streaks.loss = totals.streaks.temp_loss;
totals.streaks.temp_win = 0;
if (totals.streaks.temp_loss > 0) totals.streaks.last_loss = totals.streaks.temp_loss;
break;
case 3: //dc
totals.all.dc++;
if (O300_Selections.ShowO300PerDayGraph.value || O300_Selections.ShowO300PerDay.value) dayCounts[dayCountsKey].dc++;
if (O300_Selections.ShowO300MapStats.value) mapStats[value.mapName].dc++;
if (value.gameMode === 1) {
totals.ctf.dc++;
} else if (value.gameMode === 2) {
totals.nf.dc++;
}
$O300_Timeline.append('<div class="o300_dc o300_game" data-gamenumber="' + (data.length-key) + '">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
//streak...
i=key;
while ( (i > 0) && ((data[i-1].outcome === 4)&&(data[i-1].saved === 1)) ) {
i--;
}
if ( (totals.streaks.temp_loss === 0) || ((i > 0) && ((data[i-1].outcome === 2) || (data[i-1].outcome === 3) || (data[i-1].outcome === 5)) ) ) totals.streaks.temp_loss++;
if (totals.streaks.temp_loss > totals.streaks.loss) totals.streaks.loss = totals.streaks.temp_loss;
totals.streaks.temp_win = 0;
if (totals.streaks.temp_loss > 0) totals.streaks.last_loss = totals.streaks.temp_loss;
break;
case 4: //save attempt
if (value.saved === 1) { //failed save attempt...
totals.all.fsa++;
if (O300_Selections.ShowO300PerDayGraph.value || O300_Selections.ShowO300PerDay.value) dayCounts[dayCountsKey].fsa++;
if (O300_Selections.ShowO300MapStats.value) mapStats[value.mapName].fsa++;
if (value.gameMode === 1) {
totals.ctf.fsa++;
} else if (value.gameMode === 2) {
totals.nf.fsa++;
}
$O300_Timeline.append('<div class="o300_fsa o300_game" data-gamenumber="' + (data.length-key) + '"></div>');
}
break;
case 5: //tie
totals.all.tie++;
if (O300_Selections.ShowO300PerDayGraph.value || O300_Selections.ShowO300PerDay.value) dayCounts[dayCountsKey].tie++;
if (O300_Selections.ShowO300MapStats.value) mapStats[value.mapName].tie++;
if (value.gameMode === 1) {
totals.ctf.tie++;
} else if (value.gameMode === 2) {
totals.nf.tie++;
}
$O300_Timeline.append('<div class="o300_tie o300_game" data-gamenumber="' + (data.length-key) + '">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
//streak...
i=key;
while ( (i > 0) && ((data[i-1].outcome === 4)&&(data[i-1].saved === 1)) ) {
i--;
}
if ( (totals.streaks.temp_loss === 0) || ((i > 0) && ((data[i-1].outcome === 2) || (data[i-1].outcome === 3) || (data[i-1].outcome === 5)) ) ) totals.streaks.temp_loss++;
if (totals.streaks.temp_loss > totals.streaks.loss) totals.streaks.loss = totals.streaks.temp_loss;
totals.streaks.temp_win = 0;
if (totals.streaks.temp_loss > 0) totals.streaks.last_loss = totals.streaks.temp_loss;
break;
default: //just in case!
$O300_Timeline.append('<div class="o300_unknown" data-gamenumber="' + (data.length-key) + '">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
break;
}
});
GM_setValue('totalPotentialPowerups', totalPotentialPowerups);
setTimelineCellHeights(Cell_Width);
//Win %...
var currentWinPC = ((totals.all.win+totals.all.ssa) / (totals.all.win+totals.all.ssa + totals.all.loss+totals.all.dc+totals.all.tie) * 100).toFixed(2);
GM_setValue('currentWinPC', currentWinPC);
$O300_Messages.append('<div id="O300_Wins">Win % over your last <span style="color:' + O300_Selections.Win_Color.value + '">' + data.length + '</span> games: <span style="color:'+O300_Selections.Win_Color.value+'">' + currentWinPC + '%</span></div>');
//Game Count...
$O300_Messages.append('<div id="O300_Count" style="font-size:11px">(<span style="color:'+O300_Selections.Win_Color.value+'">' + (totals.all.win) + ' Win'+((totals.all.win)==1?'':'s')+'</span> | <span style="color:'+O300_Selections.Loss_Color.value+'">'+ (totals.all.loss) + ' Loss'+(totals.all.loss==1?'':'es')+'</span> | <span style="color:'+O300_Selections.Tie_Color.value+'" title="Ties are counted as a Loss">'+ (totals.all.tie) + ' Tie'+(totals.all.tie==1?'':'s')+'</span> | <span style="color:'+O300_Selections.DC_Color.value+'" title="DC\'s are counted as a Loss">' + totals.all.dc + ' DC'+(totals.all.dc==1?'':'s')+'</span> | <span style="color:'+O300_Selections.SSA_Color.value+'" title="Counts as a Win!">' + totals.all.ssa + ' Save'+(totals.all.ssa==1?'':'s')+'</span> | <span style="color:'+O300_Selections.FSA_Color.value+'" title="Unsuccessful Save Attempts do NOT count as a Loss (or a Win)">' + totals.all.fsa + ' USA'+(totals.all.fsa==1?'':'s')+'</span>)</div>');
//Highest/Lowest % Ever (while running this script)...
if ((data.length === 300) && (PageLoc !== 'profileNotOurs')) { //only do this once we've played 300 games. otherwise we get 'stuck' at an early high or low value.
if (currentWinPC > GM_getValue('O300_HighestEver', 0)) GM_setValue('O300_HighestEver', currentWinPC);
if ((currentWinPC < GM_getValue('O300_LowestEver', 100)) && (currentWinPC > 0)) GM_setValue('O300_LowestEver', currentWinPC);
$O300_Messages.append('<div id="O300_HighestLowestEver" title="'+O300_Selections.ShowO300HighestLowestEver.title+'"><span style="color:#2CAD9C'+(currentWinPC === GM_getValue('O300_HighestEver', 0) ? '; text-decoration:underline':'')+'" title="Highest Win % Ever">Highest: ' + GM_getValue('O300_HighestEver', 0) + '%</span> | <span style="color:#2CAD9C'+(currentWinPC === GM_getValue('O300_LowestEver', 0) ? '; text-decoration:underline':'')+'" title="Lowest Win % Ever">Lowest: ' + GM_getValue('O300_LowestEver', 0) + '%</span></div>');
} else if (data.length < 300) {
GM_deleteValue('O300_HighestEver');
GM_deleteValue('O300_LowestEver');
}
//CTF / NF...
var totalCTF = (totals.ctf.win+totals.ctf.ssa + totals.ctf.loss+totals.ctf.dc+totals.ctf.tie);
var CTFWinPC = (totalCTF === 0) ? 0 : ((totals.ctf.win+totals.ctf.ssa) / totalCTF * 100).toFixed(2);
var totalNF = (totals.nf.win+totals.nf.ssa + totals.nf.loss+totals.nf.dc+totals.nf.tie);
var NFWinPC = (totalNF === 0) ? 0 : ((totals.nf.win+totals.nf.ssa) / totalNF * 100).toFixed(2);
$O300_Messages.append('<div id="O300_CTFNF"><span id="O300_CTFWP" class="O300_CTFNFWP" style="color:#9264DA; cursor:pointer" title="Click to show CTF games">CTF ('+(totalCTF+totals.ctf.fsa)+'): ' + CTFWinPC + '%</span> | <span id="O300_NFWP" class="O300_CTFNFWP" style="color:#9264DA; cursor:pointer" title="Click to show Neutral Flag games">NF ('+(totalNF+totals.nf.fsa)+'): ' + NFWinPC + '%</span></div>');
//Oldest Game...
var oldestGame = getUsefulText( (data[0].outcome.toString() + data[0].saved.toString()), 'outcome');
$O300_Messages.append('<div id="O300_OldestGame">Oldest game: ' + (oldestGame) + '</div>');
//Next game effect...
$O300_Messages.append('<div id="O300_NextGameAffectLose">' + getNextGamePercentage(data) + '</div>');
//MapStats...
if (O300_Selections.ShowO300MapStats.value) {
$O300_Messages.append('<div id="O300_MS" style="color:cornflowerblue; cursor:pointer" title="Click for table...">MapStats</div>');
$('#O300_MS').after('<div id="O300_MS_Data" style="position:absolute; display:none; left:20px; padding:8px; font-size:10px; color:dodgerblue; background:#333; border:1px solid #ccc; border-radius:8px; overflow-x:hidden; overflow-y:auto; z-index:100">' +
'<div style="font-size:12px; color:dodgerblue">MapStats<div style="position:absolute; right:30px; display:inline-block; margin-top:-5px; font-size:10px; color:white;">Show As: <label><input type="radio" id="O300_ShowAs_Total" name="O300_ShowAs" style=""'+(GM_getValue('O300_MS_ShowAs', 'game') === 'total' ? ' checked' : '')+'>Totals</label><label><input type="radio" id="O300_ShowAs_Game" name="O300_ShowAs" style=""'+(GM_getValue('O300_MS_ShowAs', 'game') === 'game' ? ' checked' : '')+'>Per Game</label><label><input type="radio" id="O300_ShowAs_Minute" name="O300_ShowAs" style=""'+(GM_getValue('O300_MS_ShowAs', 'game') === 'minute' ? ' checked' : '')+'>Per Minute</label></div></div>');
$('#O300_MS_Data').append('<table id="O300_MS_Data_Table"></table>');
$('#O300_MS_Data_Table').append('<thead style="display:block; overflow-x:hidden; overflow-y:auto"><tr>' +
'<th class="O300_MS_90">Maps</th>' +
'<th class="O300_MS_60">Results</th>' +
'<th class="O300_MS_60">Played%</th>' +
'<th class="O300_MS_50">Time</th>' +
'<th class="O300_MS_50">Win%</th>' +
'<th class="O300_MS_35">SBP</th>' +
'<th class="O300_MS_35">Ta</th>' +
'<th class="O300_MS_35">Po</th>' +
'<th class="O300_MS_35">Gr</th>' +
'<th class="O300_MS_35">Dr</th>' +
'<th class="O300_MS_35">Ho</th>' +
'<th class="O300_MS_35">Ca</th>' +
'<th class="O300_MS_35">Pr</th>' +
'<th class="O300_MS_35">Re</th>' +
'<th class="O300_MS_35">Su</th>' +
'<th class="O300_MS_35">PU</th>' +
'</tr><tr id="O300_MS_Totals" style="font-size:10px; color:#eee; background:#444"></tr></thead>' +
'<tbody style="display:block; height:200px; overflow-x:hidden; overflow-y:auto"></tbody>');
$('#O300_MS').on('click', function() {
if ($('#O300_ASBP_Data').is(':visible')) $('#O300_ASBP_Data').hide(0);
if ($('#O300_mapPreviewWindow').is(':visible')) $('#O300_mapPreviewWindow').fadeOut(200);
$('#O300_MS_Data').slideToggle();
});
$('#O300_MS_Data_Table').find('th').click(function(e, preventReverse) {
GM_setValue('O300_MS_SortBy', $(this).index()); //save the header we're sorting by
$('#O300_MS_Data_Table').find('th').css('color', '#ddd');
$(this).css('color', 'chartreuse');
var table = $('#O300_MS_Data_Table tbody');
var rows = table.find('tr').toArray().sort(comparer($(this).index()));
if (!preventReverse) {
this.asc = !this.asc;
if (!this.asc) rows = rows.reverse();
}
for (var i = 0; i < rows.length; i++) { table.append(rows[i]); }
});
$('#O300_ShowAs_Total').on('click', function() {
if (GM_getValue('O300_MS_ShowAs') !== 'total') {
GM_setValue('O300_MS_ShowAs', 'total');
updateMapStats(mapStats, totals);
$('#O300_MS').find('input[name=O300_ShowAs]').parent('label').css('color', '#fff');
$(this).css('color', 'chartreuse');
}
});
$('#O300_ShowAs_Game').on('click', function() {
if (GM_getValue('O300_MS_ShowAs') !== 'game') {
GM_setValue('O300_MS_ShowAs', 'game');
updateMapStats(mapStats, totals);
$('#O300_MS').find('input[name=O300_ShowAs]').parent('label').css('color', '#fff');
$(this).css('color', 'chartreuse');
}
});
$('#O300_ShowAs_Minute').on('click', function() {
if (GM_getValue('O300_MS_ShowAs') !== 'minute') {
GM_setValue('O300_MS_ShowAs', 'minute');
updateMapStats(mapStats, totals);
$('#O300_MS').find('input[name=O300_ShowAs]').parent('label').css('color', '#fff');
$(this).css('color', 'chartreuse');
}
});
updateMapStats(mapStats, totals);
$('#O300_MS').html('Most Played Map:' + highestPlayedMapName + ' ('+mapStats[highestPlayedMapName].playedCount+'), Win:' + ((mapStats[highestPlayedMapName].win+mapStats[highestPlayedMapName].ssa) / (mapStats[highestPlayedMapName].playedCount-mapStats[highestPlayedMapName].fsa) * 100).toFixed(2) + '%, <span title="Average Game Length">AGL:</span>' + secondsToHMS(mapStats[highestPlayedMapName].timePlayed / mapStats[highestPlayedMapName].playedCount) );
$('#O300_MS_Data_Table').on('click', '.O300_MS_MapResults', function() {
O300_Selections.MaxO300Games.value = 'Map';
O300_Selections.MaxO300Games.title = $(this).prev('td').data('sortby');
setTimelineCellHeights(Cell_Width);
showTrimmedData(0,0);
});
$('#O300_MS').after('<div id="O300_mapPreviewWindow" style="display:none; position:absolute; border:2px solid chartreuse; border-radius:5px; text-shadow:1px 2px 1px #000; width:620px; height:370px; z-index:1000"><div id="O300_MS_MapPreviewName" style="margin-top:5px; color:#fff; font-weight:bold"></div></div>');
$('#O300_MS_Data_Table').on('click', '.O300_MS_MapName', function() {
if ($(this).data('previewid')) {
var mapPreviewURL = "http://unfortunate-maps.jukejuice.com/static/previews/" + $(this).data('previewid') + ".png";
if ( ($('#O300_mapPreviewWindow').is(':visible')) && ($('#O300_mapPreviewWindow').data('previewid') === $(this).data('previewid')) ) {
$('#O300_mapPreviewWindow').hide(0);
$('#O300_MS_Data_Table').find('.O300_MS_MapName').css('color', '#ddd');
} else {
$('#O300_mapPreviewWindow').data('previewid', $(this).data('previewid'));
$('#O300_MS_MapPreviewName').text($(this).text()+' by '+$(this).data('mapauthor'));
$('#O300_MS_Data_Table').find('.O300_MS_MapName').css('color', '#ddd');
$(this).css('color', 'chartreuse');
$('#O300_mapPreviewWindow').css('background', '#000 url(\''+mapPreviewURL+'\')');
$('#O300_mapPreviewWindow').css('background-size', 'contain');
$('#O300_mapPreviewWindow').css('background-repeat', 'no-repeat');
$('#O300_mapPreviewWindow').css('background-position', 'center');
$('#O300_mapPreviewWindow').fadeIn(400);
$('#O300_mapPreviewWindow').css({'top': $(this).position().top+$('#O300_MS_Data').position().top+16, 'left': $(this).position().left+118});
}
}
});
$('#O300_mapPreviewWindow').on('click', function() {
$('#O300_mapPreviewWindow').hide(0);
$('#O300_MS_Data_Table').find('.O300_MS_MapName').css('color', '#ddd');
});
}
//Average Scoreboard Position...
if (O300_Selections.ShowO300ASBP.value && SBP_Length) {
$O300_Messages.append('<div id="O300_ASBP" style="color:darksalmon; cursor:pointer" title="Click for table...">Average Scoreboard Position: ' + (SBP_Us_Total / SBP_Us_Count).toFixed(2) + '</div>');
$('#O300_ASBP').after('<div id="O300_ASBP_Data" style="position:absolute; display:none; margin:0 auto; padding-right:3px; font-size:11px; color:darksalmon; background:#333; overflow-x:hidden; overflow-y:auto; max-height:220px; z-index:100"></div>');
$('#O300_ASBP_Data').append('<table id="O300_ASBP_Data_Table" style=""></table>');
$('#O300_ASBP_Data_Table').append('<thead style="display:block; overflow-x:hidden; overflow-y:auto"><tr><th class="O300_ASBP_PlayerName"></th><th>#</th><th>Ave</th><th>1st</th><th>2nd</th><th>3rd</th><th>4th</th><th>5th</th><th>6th</th><th>7th</th><th>8th</th></tr></thead>' +
'<tbody style="display:block; height:200px; overflow-x:hidden; overflow-y:auto"></tbody>');
var averagePosition = 0;
for (var playerName in SBPR) {
averagePosition = ((SBPR[playerName].positions[1] + (SBPR[playerName].positions[2]*2) + (SBPR[playerName].positions[3]*3) + (SBPR[playerName].positions[4]*4) + (SBPR[playerName].positions[5]*5) + (SBPR[playerName].positions[6]*6) + (SBPR[playerName].positions[7]*7) + (SBPR[playerName].positions[8]*8)) / SBPR[playerName].playedCount).toFixed(2);
$('#O300_ASBP_Data_Table tbody').append('<tr'+(SBPR[playerName].us ? ' class="O300_ASBP_HighlightSelf"' : '')+'><td class="O300_ASBP_PlayerName'+(SBPR[playerName].us ? ' O300_ASBP_HighlightSelf' : '')+'" data-sortby="'+(SBPR[playerName].us ? 'Me' : playerName)+'">'+(SBPR[playerName].us ? 'Me' : playerName)+'</td><td data-sortby="'+SBPR[playerName].playedCount+'">'+SBPR[playerName].playedCount+'</td><td data-sortby="'+averagePosition+'">'+averagePosition+'</td><td data-sortby="'+SBPR[playerName].positions[1]+'">'+SBPR[playerName].positions[1]+'</td><td data-sortby="'+SBPR[playerName].positions[2]+'">'+SBPR[playerName].positions[2]+'</td><td data-sortby="'+SBPR[playerName].positions[3]+'">'+SBPR[playerName].positions[3]+'</td><td data-sortby="'+SBPR[playerName].positions[4]+'">'+SBPR[playerName].positions[4]+'</td><td data-sortby="'+SBPR[playerName].positions[5]+'">'+SBPR[playerName].positions[5]+'</td><td data-sortby="'+SBPR[playerName].positions[6]+'">'+SBPR[playerName].positions[6]+'</td><td data-sortby="'+SBPR[playerName].positions[7]+'">'+SBPR[playerName].positions[7]+'</td><td data-sortby="'+SBPR[playerName].positions[8]+'">'+SBPR[playerName].positions[8]+'</td></tr>');
}
var scrollToMe = function() {
$('#O300_ASBP_Data tbody').animate({ scrollTop: $('#O300_ASBP_Data_Table').find('.O300_ASBP_HighlightSelf').position().top - ( $('#O300_ASBP_Data_Table tbody').height() / 2) }, 100, 'swing');
};
$('#O300_ASBP').on('click', function() {
if ($('#O300_MS_Data').is(':visible')) $('#O300_MS_Data').hide(0);
$('#O300_ASBP_Data').slideToggle();
if ($('#O300_ASBP_Data').is(':visible')) scrollToMe();
});
$('#O300_ASBP_Data_Table').find('th').click(function(e, preventReverse) {
GM_setValue('O300_ASBP_SortBy', $(this).index()); //save the header we're sorting by
$('#O300_ASBP_Data_Table').find('th').css('color', '#ccc');
$(this).css('color', 'chartreuse');
var table = $('#O300_ASBP_Data_Table');
var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()));
if (!preventReverse) {
this.asc = !this.asc;
if (!this.asc) rows = rows.reverse();
}
for (var i = 0; i < rows.length; i++) { table.append(rows[i]); }
setTimeout(scrollToMe, 200);
});
//sort the table by last saved...
$('#O300_ASBP_Data_Table').find('th:eq('+GM_getValue('O300_ASBP_SortBy', 1)+')').trigger('click');
}
//Win % Bands...
if (data.length === 300) {
var intervalSize = O300_Selections.O300WinBands.value;
var int_win, int_loss;
var intervalWins = [];
for (i=0; i<data.length; i+=intervalSize) {
int_win=0;
int_loss=0;
for (j=i; j<i+intervalSize; j++) {
if (data[j].outcome == 1) {
int_win++;
} else if ((data[j].outcome == 2) || (data[j].outcome == 3) || (data[j].outcome == 5)) {
int_loss++;
}
}
intervalWins.push((int_win / (int_win + int_loss))*100);
if (i % intervalSize === 0) {
var IntervalCellWidth = ((Cell_Width+(O300_Selections.ShowO300ShowGap.value ? 1 : 0))*intervalSize-1);
var IntervalMarginLeft = 0;
if ((i === 0) || (i === data.length-intervalSize)) { //need to adjust for first & last cells...
IntervalCellWidth = ((Cell_Width+(O300_Selections.ShowO300ShowGap.value ? 1 : 0))*intervalSize-2);
if (i === 0) IntervalMarginLeft = 2;
}
$('#O300_Intervals').append('<div class="O300_Interval" data-firstgame="'+(data.length-i)+'" style="display:inline-block; cursor:pointer; font-size:11px; color:#777; width:'+IntervalCellWidth+'px; height:10px; ' + (i===0 ? 'border-left:1px solid #777; ' : '') + 'border-right:1px solid #777; margin-left:'+IntervalMarginLeft+'px;" title="Games: ' + (data.length-i-intervalSize+1) + '-' + (data.length-i) + ' (' +intervalSize+')">&nbsp;'+ (intervalWins[i/intervalSize]).toFixed(1) + '%</div>');
}
}
}
//Games Pie Chart...
$O300_Messages.append('<div id="O300_Pie"><canvas id="O300_GamesPieChart" width="80" height="80"></canvas></div>');
var ctx = $("#O300_GamesPieChart").get(0).getContext("2d");
var pieData = {
labels: ['Wins', 'Losses', 'Ties', 'DC\'s', 'Unsuccessful Save Attempts', 'Successful Saves'],
datasets: [
{
data: [totals.all.win, totals.all.loss, totals.all.tie, totals.all.dc, totals.all.fsa, totals.all.ssa],
backgroundColor: [O300_Selections.Win_Color.value, O300_Selections.Loss_Color.value, O300_Selections.Tie_Color.value, O300_Selections.DC_Color.value, O300_Selections.FSA_Color.value, O300_Selections.SSA_Color.value],
hoverBackgroundColor: ['#67ff67', '#ff4343', '#ffcc7b', '#fffe8d', '#51c6e7', '#88e888'],
borderWidth: 0
}
]
};
var pieLoadDelay = 500;
setTimeout(function() {
if ($("#O300_GamesPieChart").is(":visible")) {
window.requestAnimationFrame(function() {
var myPieChart = new Chart(ctx, {
type: 'doughnut',
data: pieData,
options: { legend:{display:false}, responsive:true, maintainAspectRatio:false }
});
});
}
}, pieLoadDelay);
//Best Streaks...
$O300_Messages.append('<div id="O300_BestStreak" style="text-align:center">Best Streaks: <span style="color:' + O300_Selections.Win_Color.value + '">' + totals.streaks.win + ' Win' + (totals.streaks.win == 1 ? '' : 's') + '</span> | <span style="color:' + O300_Selections.Loss_Color.value + '">' + totals.streaks.loss + ' Loss' + (totals.streaks.loss == 1 ? '' : 'es') + '</span></div>');
//Current Streak...
if (data[data.length-1].outcome === 1) {
$O300_Messages.append('<div id="O300_CurrentStreak" style="text-align:center">Current Streak: <span style="color:' + O300_Selections.Win_Color.value + '">' + totals.streaks.last_win + ' Win' + (totals.streaks.last_win == 1 ? '' : 's') + '</span></div>');
} else if ((data[data.length-1].outcome === 2) || (data[data.length-1].outcome === 3)) {
$O300_Messages.append('<div id="O300_CurrentStreak" style="text-align:center">Current Streak: <span style="color:' + O300_Selections.Loss_Color.value + '">' + totals.streaks.last_loss + ' Loss' + (totals.streaks.last_loss == 1 ? '' : 'es') + '</span></div>');
}
//Best Streak Messages...
if ( (data[data.length-1].outcome === 1) && (totals.streaks.last_win >= totals.streaks.win) && (data.length > 5) ) {
$O300_Messages.append('<div id="O300_BestStreakMessage" style="padding:3px 0; text-align:center; border-radius:5px; color:#fff; background-color:' + O300_Selections.Win_Color.value + '">You are currently on your best win streak!!!</div>');
} else if ( (data[data.length-1].outcome === 1) && (totals.streaks.last_win == totals.streaks.win-1) && (data.length > 5) ) {
$O300_Messages.append('<div id="O300_BestStreakMessage" style="padding:3px 0; text-align:center; border-radius:5px; color:#fff; background-color:' + O300_Selections.Win_Color.value + '">You are just <u>1 win away</u> from your best win streak!</div>');
}
//Worst Streak Messages...
if ( ((data[data.length-1].outcome === 2) || (data[data.length-1].outcome === 3)) && (totals.streaks.last_loss >= totals.streaks.loss) && (data.length > 5) ) {
$O300_Messages.append('<div id="O300_WorstStreakMessage" style="padding:3px 0; text-align:center; border-radius:5px; color:#fff; background-color:' + O300_Selections.Loss_Color.value + '">You are currently on your worst losing streak :(</div>');
} else if ( ((data[data.length-1].outcome === 2) || (data[data.length-1].outcome === 3)) && (totals.streaks.last_loss == totals.streaks.loss-1) && (data.length > 5) ) {
$O300_Messages.append('<div id="O300_WorstStreakMessage" style="padding:3px 0; text-align:center; border-radius:5px; color:#fff; background-color:' + O300_Selections.Loss_Color.value + '">You are only <u>1 loss away</u> from your worst losing streak...</div>');
}
//# Games Per Day Bar Graph...
if (O300_Selections.ShowO300PerDayGraph.value || O300_Selections.ShowO300PerDay.value) {
var minPlays=1000, maxPlays=0, daysWithGamesCount=0;
var gamesperday_barwidth = Math.floor(300 / dayCounts.length);
if (gamesperday_barwidth < 1) gamesperday_barwidth = 1;
if (gamesperday_barwidth > 10) gamesperday_barwidth = 10;
$.each(dayCounts, function(key, value) {
i = (value.win+value.loss+value.dc+value.ssa+value.fsa+value.tie);
if (i > maxPlays) maxPlays = i;
if (i < minPlays) minPlays = i;
if (i > 0) daysWithGamesCount++;
});
if (O300_Selections.AlwaysShowLastDayPlayed.value) {
O300_Selections.MaxO300Games.value = data.length - dayCounts[dayCounts.length-1].firstGameNumber;
}
var totalTimePlayed = 0;
$O300_Messages.append('<div id="O300_GamesPerDayGraph" style="display:flex; align-items:baseline; width:'+(dayCounts.length*(gamesperday_barwidth+(dayCounts.length < 200 ? 1 : 0)))+'px; max-width:420px; margin:2px auto 0; border-bottom:1px solid #fff"></div>');
var $O300_GamesPerDayGraph = $('#O300_GamesPerDayGraph');
var minBarHeight = maxPlays - minPlays;
if (minBarHeight > 10) minBarHeight = 10;
$.each(dayCounts, function(key, value) {
i = (value.win+value.loss+value.dc+value.ssa+value.fsa+value.tie);
totalTimePlayed += dayCounts[key].timePlayed;
$O300_GamesPerDayGraph.append('<div id="O300_GamesPerDay_Bar_'+key+'" class="O300_GamesPerDay_Bar" data-firstgame="'+(data.length-value.firstGameNumber)+'" data-gamecount="'+i+'" style="height:'+scaleBetween(i, (i?minBarHeight:0), 30, minPlays, maxPlays)+'px; width:'+gamesperday_barwidth+'px" title="'+i+' Games on ' + dayCounts[key].day + " (" + secondsToHMS(dayCounts[key].timePlayed) + " played)\n"+value.win+' Wins, '+ value.loss+' Losses, '+ value.tie +' Ties,'+ value.dc+' DCs, '+ value.ssa+' Saves, '+ value.fsa+' USAs"></div>');
$('#O300_GamesPerDay_Bar_'+key).append('<div style="position:absolute; background:'+O300_Selections.Win_Color.value+'; bottom:0px; width:'+gamesperday_barwidth+'px; height:'+((value.win+value.ssa)/i*100)+'%"></div>');
});
GM_addStyle('.O300_GamesPerDay_Bar { position:relative; margin-left:'+(dayCounts.length < 200 ? 1 : 0)+'px; background:#666 }');
GM_addStyle('.O300_GamesPerDay_Bar:hover { opacity:0.6 }');
//# Games Per Day...
$O300_Messages.append('<div id="O300_GamesPerDay" style="font-size:11px">' + daysWithGamesCount + ' Game Days (' + (data.length/daysWithGamesCount).toFixed(2) + ' games/day, ' + secondsToHMS(totalTimePlayed/daysWithGamesCount) + ' mins/day)</div>');
}
//Other Players Win%...
if (O300_Selections.ShowOtherPlayers.value === true) {
if (((PageLoc === 'server') || (PageLoc === 'profile')) && okToRequestServerData()) { //only 'get' the data if we haven't done so recently
$('#O300_OtherPlayersStats_Add_Spin').addClass('O300_RotateAddText');
setupStats();
setTimeout(function() {
getProfilesData();
}, delayLoadingBy);
} else { //show the cached data...
$('#O300_OtherPlayersStats_Add_Spin').addClass('O300_RotateAddText');
setupStats();
showProfiles();
}
}
//Per-Game Stats Table...
$('#O300_MessagesPie').after('<table id="O300_Stats">' +
' <tr><th></th></tr>' +
' <tr><th style="text-align:right" title="Green is better than the Scoreboard Average. Red is worse.">Per Game:</th></tr>' +
' <tr><th style="text-align:right" title="Average of all player stats on the scoreboard, across all these games">S/B Ave:</th></tr>' +
'</table>');
var s1, s2, color;
$.each(totals.mystats, function(key, value) {
var keytitle='';
if (key === 'powerups') {
keytitle = 'PUPs';
} else if (key === 'captures') {
keytitle = 'Caps';
} else {
keytitle = capitaliseFirstLetter(key);
}
if (key !== 'timePlayed') {
$('#O300_Stats').find('tr:eq(0)').append('<th>'+keytitle+'</th>');
s1 = value/data.length;
s2 = totals.allstats[key] / totals.allstats.count;
if ((key === 'pops') || (key === 'drops')) {
if (s1 > s2) color = '#b00';
else color = '#0a0';
} else {
if (s1 < s2) color = '#b00';
else color = '#0a0';
}
if ((key === 'hold') || (key === 'prevent')) {
$('#O300_Stats').find('tr:eq(1)').append('<td style="color:'+color+'">'+secondsToHMS(s1)+'</td>');
$('#O300_Stats').find('tr:eq(2)').append('<td>'+secondsToHMS(s2)+'</td>');
} else {
$('#O300_Stats').find('tr:eq(1)').append('<td style="color:'+color+'">'+(s1).toFixed(2)+'</td>');
$('#O300_Stats').find('tr:eq(2)').append('<td>'+(s2).toFixed(2)+'</td>');
}
} else {
$('#O300_Stats').find('tr:eq(0)').append('<th>Time</th>');
$('#O300_Stats').find('tr:eq(1)').append('<td>'+secondsToHMS(value/data.length)+'</td>');
$('#O300_Stats').find('tr:eq(2)').append('<td>-</td>');
$('#O300_Stats').find('tr:eq(0)').append('<th>C/G</th>');
s1 = totals.mystats.captures / totals.mystats.grabs;
s2 = totals.allstats.captures / totals.allstats.grabs;
if (s1 < s2) color = '#b00';
else color = '#0a0';
$('#O300_Stats').find('tr:eq(1)').append('<td style="color:'+color+'">'+(s1).toFixed(3)+'</td>');
$('#O300_Stats').find('tr:eq(2)').append('<td>'+(s2).toFixed(3)+'</td>');
$('#O300_Stats').find('tr:eq(0)').append('<th>K/D</th>');
s1 = totals.mystats.tags / totals.mystats.pops;
s2 = totals.allstats.tags / totals.allstats.pops;
if (s1 < s2) color = '#b00';
else color = '#0a0';
$('#O300_Stats').find('tr:eq(1)').append('<td style="color:'+color+'">'+(s1).toFixed(3)+'</td>');
$('#O300_Stats').find('tr:eq(2)').append('<td>'+(s2).toFixed(3)+'</td>');
}
});
$('#O300_GamesPerDayGraph').find('.O300_GamesPerDay_Bar').on('click', function() {
O300_Selections.MaxO300Games.value = $(this).data('firstgame');
GM_setValue('O300_Selections', O300_Selections);
setTimelineCellHeights(Cell_Width);
showTrimmedData($(this).data('firstgame'), $(this).data('gamecount'));
});
$('#O300_Intervals').find('.O300_Interval').on('click', function() {
O300_Selections.MaxO300Games.value = $(this).data('firstgame');
GM_setValue('O300_Selections', O300_Selections);
setTimelineCellHeights(Cell_Width);
$('#O300_Intervals .O300_Interval').css('color', '#777');
$(this).css('color', '#ddd');
showTrimmedData($(this).data('firstgame'), intervalSize);
});
$('#O300_Timeline div').on('click', function() {
O300_Selections.MaxO300Games.value = $(this).data('gamenumber');
GM_setValue('O300_Selections', O300_Selections);
setTimelineCellHeights(Cell_Width);
$('#O300_Intervals .O300_Interval').css('color', '#777');
showTrimmedData($(this).data('gamenumber'), $(this).data('gamenumber'));
});
$('#O300_CTFWP').on('click', function(){
O300_Selections.MaxO300Games.value = 'CTF';
GM_setValue('O300_Selections', O300_Selections);
setTimelineCellHeights(Cell_Width);
showTrimmedData(0,0);
});
$('#O300_NFWP').on('click', function(){
O300_Selections.MaxO300Games.value = 'NF';
GM_setValue('O300_Selections', O300_Selections);
setTimelineCellHeights(Cell_Width);
showTrimmedData(0,0);
});
$('#O300_Timeline').find('.o300_game').hoverIntent(function() {
if ($('#O300_GameInfo').parent().attr('id') !== 'O300t_Timeline') $('#O300_Timeline').prepend( $('#O300_GameInfo') );
showGameInfo($(this).data('gamenumber')-1, $(this).position().top+15, $(this).position().left-200);
}, function() {
$('#O300_GameInfo').hide(0);
});
}
/************************************************************************************/
// Mini Timeline...
/************************************************************************************/
function showTrimmedData(start, count) {
var WinPercentageText;
var Timeline_MaxWidth = 390;
var Cell_Width = 8; //This value will adjust (smaller) according to MaxGames & Timeline_MaxWidth. Default=8
var ShowGapMarginLeft = 1;
var i;
var totals = {'all': { win:0, loss:0, dc:0, ssa:0, fsa:0, tie:0 },
'ctf': { win:0, loss:0, dc:0, ssa:0, fsa:0, tie:0 },
'nf': { win:0, loss:0, dc:0, ssa:0, fsa:0, tie:0 },
'mystats': { tags:0, pops:0, grabs:0, drops:0, hold:0, captures:0, prevent:0, returns:0, support:0, powerups:0, timePlayed:0 },
'allstats': { tags:0, pops:0, grabs:0, drops:0, hold:0, captures:0, prevent:0, returns:0, support:0, powerups:0, timePlayed:0, count:0 },
'streaks': { win:0, loss:0, temp_win:0, temp_loss:0, last_win:0, last_loss:0 }
};
var data = $.extend(true, [], allGames);
var newData = [];
var key, l;
if (O300_Selections.MaxO300Games.value === 'CTF') {
for (key=0, l=data.length; key<l; key++) {
if (data[key].gameMode === 1) newData.push(data[key]);
}
data = $.extend(true, [], newData);
start = data.length;
count = data.length;
WinPercentageText = 'Win % over these <span style="color:' + O300_Selections.Win_Color.value + '">' + data.length + '</span> CTF games:';
} else if (O300_Selections.MaxO300Games.value === 'NF') {
for (key=0, l=data.length; key<l; key++) {
if (data[key].gameMode === 2) newData.push(data[key]);
}
data = $.extend(true, [], newData);
start = data.length;
count = data.length;
WinPercentageText = 'Win % over these <span style="color:' + O300_Selections.Win_Color.value + '">' + data.length + '</span> NF games:';
} else if (O300_Selections.MaxO300Games.value === 'Map') {
for (key=0, l=data.length; key<l; key++) {
if (data[key].mapName === O300_Selections.MaxO300Games.title) newData.push(data[key]);
}
data = $.extend(true, [], newData);
start = data.length;
count = data.length;
WinPercentageText = 'Win % over these <span style="color:' + O300_Selections.Win_Color.value + '">' + data.length + ' ' + O300_Selections.MaxO300Games.title + '</span> games:';
} else if ($.isNumeric(O300_Selections.MaxO300Games.value)) {
if (!start) start = 0;
if (!count) count = data.length;
$O300_Timeline.find('[data-gamenumber="' + start + '"]').css('height', '+=6');
if (count > 1) $O300_Timeline.find('[data-gamenumber="' + (start-count+1) + '"]').css('height', '+=6');
start = data.length-start;
data = data.splice(start, count);
WinPercentageText = 'Win % over these <span style="color:' + O300_Selections.Win_Color.value + '">' + data.length + '</span> games ' + (start>=0 ? '('+(allGames.length-start-count+1)+'-'+(allGames.length-start)+'): ' : '');
}
if (count > 200) ShowGapMarginLeft = 0;
var New_Cell_Width = Math.floor((Timeline_MaxWidth - 34) / data.length);
if (New_Cell_Width < Cell_Width) Cell_Width = New_Cell_Width - (O300_Selections.ShowO300ShowGap.value ? (count > 200 ? 0 : 1) : 0);
if (Cell_Width <= 0) Cell_Width = 1;
var NF_Marker = '<div title="Neutral Flag Game" style="position:absolute; width:'+Cell_Width+'px; height:1px; bottom:-2px; background:#ccc"></div>';
$O300T_Timeline.empty();
$O300T_Messages.empty();
$('#O300T_Pie').remove();
$('#O300T_PUPs').remove();
var totalPotentialPowerups = 0;
var SBP_Total = 0, SBP_Count = 0;
$.each(data, function(key, value) {
totalPotentialPowerups += value.potentialPowerups;
$.each(totals.mystats, function(key1, value1) {
totals.mystats[key1] += value[key1];
});
if (value.hasOwnProperty('playersData')) {
$.each(value.playersData, function(key1, value1) {
if (value1.us === true) {
SBP_Total += key1+1;
SBP_Count++;
}
if (value1.tags + value1.pops + value1.grabs + value1.prevent + value1.support > 10) { //remove lowly players (probably very late joiners)
totals.allstats.tags += value1.tags;
totals.allstats.pops += value1.pops;
totals.allstats.grabs += value1.grabs;
totals.allstats.drops += value1.drops;
totals.allstats.hold += value1.hold;
totals.allstats.captures += value1.captures;
totals.allstats.prevent += value1.prevent;
totals.allstats.returns += value1.returns;
totals.allstats.support += value1.support;
totals.allstats.powerups += value1.powerups;
totals.allstats.score += value1.score;
totals.allstats.points += value1.points;
totals.allstats.count++;
} else {
//console.log('Player joined late? Game #:'+key + ' (not counting): '+value1.name);
}
});
}
switch (value.outcome) {
case 1: //win
if (value.saved === 2) {
totals.all.ssa++;
if (value.gameMode === 1) {
totals.ctf.ssa++;
} else if (value.gameMode === 2) {
totals.nf.ssa++;
}
$O300T_Timeline.append('<div class="o300t_ssa o300_game" data-gamenumber="' + (value.gameNumber) + '">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
} else {
totals.all.win++;
if (value.gameMode === 1) {
totals.ctf.win++;
} else if (value.gameMode === 2) {
totals.nf.win++;
}
$O300T_Timeline.append('<div class="o300t_win o300_game" data-gamenumber="' + (value.gameNumber) + '">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
}
//streak...
i=key;
while ( (i > 0) && ((data[i-1].outcome === 4)&&(data[i-1].saved === 1)) ) { //unsuccessful saves shouldn't break a streak!
i--;
}
if ( (totals.streaks.temp_win === 0) || ((i > 0) && ((data[i-1].outcome === 1)) ) ) totals.streaks.temp_win++;
if (totals.streaks.temp_win > totals.streaks.win) totals.streaks.win = totals.streaks.temp_win;
totals.streaks.temp_loss = 0;
if (totals.streaks.temp_win > 0) totals.streaks.last_win = totals.streaks.temp_win;
break;
case 2: //loss
totals.all.loss++;
if (value.gameMode === 1) {
totals.ctf.loss++;
} else if (value.gameMode === 2) {
totals.nf.loss++;
}
$O300T_Timeline.append('<div class="o300t_loss o300_game" data-gamenumber="' + (value.gameNumber) + '">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
//streak...
i=key;
while ( (i > 0) && ((data[i-1].outcome === 4)&&(data[i-1].saved === 1)) ) { //unsuccessful saves shouldn't break a streak!
i--;
}
if ( (totals.streaks.temp_loss === 0) || ((i > 0) && ((data[i-1].outcome === 2) || (data[i-1].outcome === 3) || (data[i-1].outcome === 5)) ) ) totals.streaks.temp_loss++;
if (totals.streaks.temp_loss > totals.streaks.loss) totals.streaks.loss = totals.streaks.temp_loss;
totals.streaks.temp_win = 0;
if (totals.streaks.temp_loss > 0) totals.streaks.last_loss = totals.streaks.temp_loss;
break;
case 3: //dc
totals.all.dc++;
if (value.gameMode === 1) {
totals.ctf.dc++;
} else if (value.gameMode === 2) {
totals.nf.dc++;
}
$O300T_Timeline.append('<div class="o300t_dc o300_game" data-gamenumber="' + (value.gameNumber) + '">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
//streak...
i=key;
while ( (i > 0) && ((data[i-1].outcome === 4)&&(data[i-1].saved === 1)) ) { //unsuccessful saves shouldn't break a streak!
i--;
}
if ( (totals.streaks.temp_loss === 0) || ((i > 0) && ((data[i-1].outcome === 2) || (data[i-1].outcome === 3) || (data[i-1].outcome === 5)) ) ) totals.streaks.temp_loss++;
if (totals.streaks.temp_loss > totals.streaks.loss) totals.streaks.loss = totals.streaks.temp_loss;
totals.streaks.temp_win = 0;
if (totals.streaks.temp_loss > 0) totals.streaks.last_loss = totals.streaks.temp_loss;
break;
case 4: //save attempt
if (value.saved === 1) { //failed save attempt...
totals.all.fsa++;
if (value.gameMode === 1) {
totals.ctf.fsa++;
} else if (value.gameMode === 2) {
totals.nf.fsa++;
}
$O300T_Timeline.append('<div class="o300t_fsa o300_game" data-gamenumber="' + (value.gameNumber) + '">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
}
break;
case 5: //tie
totals.all.tie++;
if (value.gameMode === 1) {
totals.ctf.tie++;
} else if (value.gameMode === 2) {
totals.nf.tie++;
}
$O300T_Timeline.append('<div class="o300t_tie o300_game" data-gamenumber="' + (value.gameNumber) + '">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
//streak...
i=key;
while ( (i > 0) && ((data[i-1].outcome === 4)&&(data[i-1].saved === 1)) ) { //unsuccessful saves shouldn't break a streak!
i--;
}
if ( (totals.streaks.temp_loss === 0) || ((i > 0) && ((data[i-1].outcome === 2) || (data[i-1].outcome === 3) || (data[i-1].outcome === 5)) ) ) totals.streaks.temp_loss++;
if (totals.streaks.temp_loss > totals.streaks.loss) totals.streaks.loss = totals.streaks.temp_loss;
totals.streaks.temp_win = 0;
if (totals.streaks.temp_loss > 0) totals.streaks.last_loss = totals.streaks.temp_loss;
break;
default: //just in case!
$O300T_Timeline.append('<div class="o300t_unknown" data-gamenumber="' + (value.gameNumber) + '" title="Unknown Result">'+(value.gameMode === 2 ? NF_Marker : '')+'</div>');
break;
}
});
$('#O300T_Timeline').find('.o300t_win').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? ShowGapMarginLeft : 0)+'px', 'background-color':O300_Selections.Win_Color.value, 'height':'6px', 'width':Cell_Width+'px' });
$('#O300T_Timeline').find('.o300t_loss').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? ShowGapMarginLeft : 0)+'px', 'background-color':O300_Selections.Loss_Color.value, 'height':'6px', 'width':Cell_Width+'px' });
$('#O300T_Timeline').find('.o300t_dc').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? ShowGapMarginLeft : 0)+'px', 'background-color':O300_Selections.DC_Color.value, 'height':'6px', 'width':Cell_Width+'px' });
$('#O300T_Timeline').find('.o300t_ssa').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? ShowGapMarginLeft : 0)+'px', 'background-color':O300_Selections.SSA_Color.value, 'height':'6px', 'width':Cell_Width+'px', 'border-top' :'2px solid white' });
$('#O300T_Timeline').find('.o300t_fsa').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? ShowGapMarginLeft : 0)+'px', 'background-color':O300_Selections.FSA_Color.value, 'height':'6px', 'width':Cell_Width+'px', 'border-bottom':'2px solid white' });
$('#O300T_Timeline').find('.o300t_tie').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? ShowGapMarginLeft : 0)+'px', 'background-color':O300_Selections.Tie_Color.value, 'height':'6px', 'width':Cell_Width+'px' });
$('#O300T_Timeline').find('.o300t_unknown').css ({ 'display':'inline-block', 'position':'relative', 'border-radius':'2px', 'margin-left':(O300_Selections.ShowO300ShowGap.value ? ShowGapMarginLeft : 0)+'px', 'background-color':O300_Selections.Unknown_Color.value, 'height':'6px', 'width':Cell_Width+'px' });
//Win %...
var currentWinPC = ((totals.all.win+totals.all.ssa) / (totals.all.win+totals.all.ssa + totals.all.loss+totals.all.dc+totals.all.tie) * 100).toFixed(2);
$O300T_Messages.append('<div id="O300T_Wins">' + WinPercentageText + ' <span style="color:'+O300_Selections.Win_Color.value+'">' + currentWinPC + '%</span></div>');
//Games Count...
$O300T_Messages.append('<div id="O300T_Count">(<span style="color:'+O300_Selections.Win_Color.value+'">' + (totals.all.win) + ' Win'+((totals.all.win)==1?'':'s')+'</span> | <span style="color:'+O300_Selections.Loss_Color.value+'">'+ (totals.all.loss) + ' Loss'+(totals.all.loss==1?'':'es')+'</span> | <span style="color:'+O300_Selections.Tie_Color.value+'" title="Ties are counted as a Loss">'+ (totals.all.tie) + ' Tie'+(totals.all.tie==1?'':'s')+'</span> | <span style="color:'+O300_Selections.DC_Color.value+'" title="DC\'s are counted as a Loss">' + totals.all.dc + ' DC'+(totals.all.dc==1?'':'s')+'</span> | <span style="color:'+O300_Selections.SSA_Color.value+'" title="Counts as a Win!">' + totals.all.ssa + ' Save'+(totals.all.ssa==1?'':'s')+'</span> | <span style="color:'+O300_Selections.FSA_Color.value+'" title="Unsuccessful Save Attempts do NOT count as a Loss (or a Win)">' + totals.all.fsa + ' USA'+(totals.all.fsa==1?'':'s')+'</span>)</div>');
//CTF / NF...
var totalCTF = (totals.ctf.win+totals.ctf.ssa + totals.ctf.loss+totals.ctf.dc+totals.ctf.tie);
var CTFWinPC = (totalCTF === 0) ? 0 : ((totals.ctf.win+totals.ctf.ssa) / totalCTF * 100).toFixed(2);
var totalNF = (totals.nf.win+totals.nf.ssa + totals.nf.loss+totals.nf.dc+totals.nf.tie);
var NFWinPC = (totalNF === 0) ? 0 : ((totals.nf.win+totals.nf.ssa) / totalNF * 100).toFixed(2);
$O300T_Messages.append('<div id="O300T_CTFNF"><span style="color:#9264DA">CTF ('+(totalCTF+totals.ctf.fsa)+'): ' + CTFWinPC + '%</span> | <span style="color:#9264DA">NF ('+(totalNF+totals.nf.fsa)+'): ' + NFWinPC + '%</span></div>');
//Best Streaks...
$O300T_Messages.append('<div id="O300T_BestStreak" style="text-align:center">Best Streaks: <span style="color:' + O300_Selections.Win_Color.value + '">' + totals.streaks.win + ' Win' + (totals.streaks.win == 1 ? '' : 's') + '</span> | <span style="color:' + O300_Selections.Loss_Color.value + '">' + totals.streaks.loss + ' Loss' + (totals.streaks.loss == 1 ? '' : 'es') + '</span></div>');
//Average Scoreboard Position...
$O300T_Messages.append('<div id="O300T_ASBP" style="font-size:11px; color:darksalmon">Average Scoreboard Position: ' + (SBP_Total / SBP_Count).toFixed(2) + '</div>');
//Games Mini Pie Chart...
if (O300_Selections.ShowO300TrimmedGamesPieChart.value) {
$O300T_Messages.append('<div id="O300T_Pie"><canvas id="O300T_GamesPieChart" width="50" height="50"></canvas></div>');
var ctx = $("#O300T_GamesPieChart").get(0).getContext("2d");
var pieData = {
labels: ['Wins', 'Losses', 'Ties', 'DC\'s', 'Unsuccessful Save Attempts', 'Successful Saves'],
datasets: [
{
data: [totals.all.win, totals.all.loss, totals.all.tie, totals.all.dc, totals.all.fsa, totals.all.ssa],
backgroundColor: [O300_Selections.Win_Color.value, O300_Selections.Loss_Color.value, O300_Selections.Tie_Color.value, O300_Selections.DC_Color.value, O300_Selections.FSA_Color.value, O300_Selections.SSA_Color.value],
hoverBackgroundColor: ['#67ff67', '#ff4343', '#ffcc7b', '#fffe8d', '#51c6e7', '#88e888'],
borderWidth: 0
}
]
};
var pieLoadDelay = 500;
setTimeout(function() {
if ($("#O300T_GamesPieChart").is(":visible")) {
window.requestAnimationFrame(function() {
var myPieChart = new Chart(ctx, {
type: 'doughnut',
data: pieData,
options: { legend:{display:false}, responsive:true, maintainAspectRatio:false }
});
});
}
}, pieLoadDelay);
}
//Power Up Stats...
if (O300_Selections.ShowO300TrimmedPUPs.value) {
$O300T_Messages.append('<div id="O300T_PUPs" style="max-width:300px; margin:5px auto; display:flex; flex-wrap:wrap; justify-content:center; align-items:center; font-family:monospace; font-size:11px; border:1px solid #222; border-radius:3px; cursor:pointer"></div>');
$('#O300T_PUPs').on('click', function(){
O300_Selections.ShowO300PUPsPerGame.value = !O300_Selections.ShowO300PUPsPerGame.value;
GM_setValue('O300_Selections', O300_Selections);
$('#ShowO300PUPsPerGame').prop('checked', O300_Selections.ShowO300PUPsPerGame.value);
if (O300_Selections.ShowO300PUPsPerGame.value === true) {
$('#O300T_PUPs').find('.O300_pups_pergame').show(0);
$('#O300T_PUPs').find('.O300_pups_total').hide(0);
} else {
$('#O300T_PUPs').find('.O300_pups_pergame').hide(0);
$('#O300T_PUPs').find('.O300_pups_total').show(0);
}
});
var s1, s2, color;
$.each(totals.mystats, function(key, value) {
var keytitle='';
if (key === 'powerups') {
keytitle = 'PUPs';
} else if (key === 'captures') {
keytitle = 'Caps';
} else {
keytitle = capitaliseFirstLetter(key);
}
if (key !== 'timePlayed') {
s1 = value/data.length;
s2 = totals.allstats[key] / totals.allstats.count;
if ((key === 'pops') || (key === 'drops')) {
if (s1 > s2) color = '#b00';
else color = '#0a0';
} else {
if (s1 < s2) color = '#b00';
else color = '#0a0';
}
if ((key === 'hold') || (key === 'prevent')) {
$('#O300T_PUPs').append('<div class="O300_pups_pergame" style="margin:0 7px;' + (O300_Selections.ShowO300PUPsPerGame.value ? '' : 'display:none') + '" title="My Average '+keytitle+' Per Game: '+secondsToHMS(s1)+'\nScoreboard Average: '+secondsToHMS(s2)+'\n[Green is Better, Red is Worse]\n(Click for Totals)"><u>'+keytitle+'</u><br><span style="color:'+color+'; ">'+secondsToHMS(s1)+'</span></div>');
$('#O300T_PUPs').append('<div class="O300_pups_total" style="margin:0 7px;' + (O300_Selections.ShowO300PUPsPerGame.value ? 'display:none' : '') + '" title="My Total '+keytitle+'\n(Click for Per-Game)"><u>'+keytitle+'</u><br>'+secondsToHMS(value)+'</div>');
} else {
$('#O300T_PUPs').append('<div class="O300_pups_pergame" style="margin:0 7px;' + (O300_Selections.ShowO300PUPsPerGame.value ? '' : 'display:none') + '" title="My Average '+keytitle+' Per Game: '+(s1).toFixed(2)+'\nScoreboard Average: '+(s2).toFixed(2)+'\n[Green is Better, Red is Worse]\n(Click for Totals)"><u>'+keytitle+'</u><br><span style="color:'+color+'; ">'+(s1).toFixed(2)+'</span></div>');
$('#O300T_PUPs').append('<div class="O300_pups_total" style="margin:0 7px;' + (O300_Selections.ShowO300PUPsPerGame.value ? 'display:none' : '') + '" title="My Total '+keytitle+'\n(Click for Per-Game)"><u>'+keytitle+'</u><br>'+(value)+'</div>');
}
} else {
$('#O300T_PUPs').append('<div class="O300_pups_pergame" style="margin:0 7px;' + (O300_Selections.ShowO300PUPsPerGame.value ? '' : 'display:none') + '" title="My Average Time Per Game: '+secondsToHMS(value/data.length)+'\n(Click for Totals)"><u>Time</u><br>'+secondsToHMS(value/data.length)+'</div>');
$('#O300T_PUPs').append('<div class="O300_pups_total" style="margin:0 7px;' + (O300_Selections.ShowO300PUPsPerGame.value ? 'display:none' : '') + '" title="My Total Time\n(Click for Per-Game)"><u>Time</u><br>'+secondsToHMS(value)+'</div>');
s1 = totals.mystats.captures / totals.mystats.grabs;
s2 = totals.allstats.captures / totals.allstats.grabs;
if (s1 < s2) color = '#b00';
else color = '#0a0';
$('#O300T_PUPs').append('<div class="O300_pups_pergame" style="margin:0 7px;' + (O300_Selections.ShowO300PUPsPerGame.value ? '' : 'display:none') + '" title="My Caps/Grab Per Game: '+(s1).toFixed(3)+'\nScoreboard Average: '+(s2).toFixed(3)+'\n[Green is Better, Red is Worse]"><u>C/G</u><br><span style="color:'+color+'; ">'+(s1).toFixed(3)+'</span></div>');
$('#O300T_PUPs').append('<div class="O300_pups_total" style="margin:0 7px;' + (O300_Selections.ShowO300PUPsPerGame.value ? '' : 'display:none') + '" title="My Caps/Grab Per Game: '+(s1).toFixed(3)+'\nScoreboard Average: '+(s2).toFixed(3)+'"><u>C/G</u><br>'+(s1).toFixed(3)+'</div>');
$('#O300T_Stats').find('tr:eq(0)').append('<th>K/D</th>');
s1 = totals.mystats.tags / totals.mystats.pops;
s2 = totals.allstats.tags / totals.allstats.pops;
if (s1 < s2) color = '#b00';
else color = '#0a0';
$('#O300T_PUPs').append('<div class="O300_pups_pergame" style="margin:0 7px;' + (O300_Selections.ShowO300PUPsPerGame.value ? '' : 'display:none') + '" title="My Tags/Pop (K/D) Per Game: '+(s1).toFixed(3)+'\nScoreboard Average: '+(s2).toFixed(3)+'\n[Green is Better, Red is Worse]"><u>K/D</u><br><span style="color:'+color+'; ">'+(s1).toFixed(3)+'</span></div>');
$('#O300T_PUPs').append('<div class="O300_pups_total" style="margin:0 7px;' + (O300_Selections.ShowO300PUPsPerGame.value ? '' : 'display:none') + '" title="My Tags/Pop (K/D) Per Game: '+(s1).toFixed(3)+'\nScoreboard Average: '+(s2).toFixed(3)+'"><u>K/D</u><br>'+(s1).toFixed(3)+'</div>');
}
});
$('#O300T_Timeline').find('.o300_game').hoverIntent(function() {
if ($('#O300_GameInfo').parent().attr('id') !== 'O300_Trimmed') $('#O300_Trimmed').prepend( $('#O300_GameInfo') );
showGameInfo($(this).data('gamenumber')-1, $(this).position().top+10, $(this).position().left-200);
}, function() {
$('#O300_GameInfo').hide(0);
});
}
}
tagpro.ready(function() {
if (PageLoc === 'ingame') { //in a game
var joinTime;
var gameData = {};
var mapName='', mapAuthor='', mapType='';
var pupsCount = 0;
var result = 0;
var saveAttempt = false;
var groupPause = false;
if ((tagpro.group.socket) && (tagpro.group.socket.connected)) {
groupPause = true;
}
tagpro.socket.on('spectator', function(spectator) {
if (!spectator) {
joinTime = Date.now();
}
});
tagpro.socket.on('time', function(message) {
if (tagpro.state === 3) { //before the actual start
joinTime = Date.now();
} else if (tagpro.state === 1) { //game has started
if (!joinTime) {
joinTime = Date.now(); //time we joined (mid-game)
}
}
});
tagpro.socket.on('map', function(data) {
mapName = data.info.name;
mapAuthor = data.info.author;
setTimeout(function() {
for (var i=0; i<tagpro.map.length; i++) {
for (var j=0; j<tagpro.map[i].length; j++) {
if (tagpro.map[i][j] == 16 || (tagpro.map[i][j] == 16.1)) { //yellow flag found
mapType = 2;
} else if ((tagpro.map[i][j] == 3) || (tagpro.map[i][j] == 3.1) || (tagpro.map[i][j] == 4) || (tagpro.map[i][j] == 4.1)) { //red or blue flag found
mapType = 1;
} else if ((tagpro.map[i][j] == 6) || (tagpro.map[i][j] == 6.1) || (tagpro.map[i][j] == 6.2) || (tagpro.map[i][j] == 6.3) || (tagpro.map[i][j] == 6.4)) { //counts the pups so we can work out potential pups later
pupsCount++;
}
}
}
}, 100);
});
tagpro.socket.on('settings', function(data) {
if (tagpro.settings.stats === false) {
$('.O300_Stats_Dependent').css('text-decoration', 'line-through').css('text-shadow', 'none');
$('.O300_Stats_Dependent').attr('title', 'Stats are OFF');
}
});
tagpro.socket.on('chat', function(data) {
if (data.from === null) { //system message
if (data.message.indexOf('This is a save attempt!') >= 0) {
saveAttempt = true;
}
}
});
tagpro.socket.on('end', function(data) {
if ((!tagpro.spectator) && (!groupPause)) { //(!tagpro.settings.stats) &&
var fullTime = Date.parse(tagpro.gameEndsAt); //expected end of game time after 12 mins
var endTime = new Date().getTime(); //actual end of game time
var startTime = fullTime - 12 * 60 * 1000; //start of game time
var fullGameLength = (endTime-startTime)/1000; //how long the whole game lasted (with or without us)
var playedGameLength = (endTime-joinTime)/1000; //how long we played for
var playerCount = 0;
for (var playerId in tagpro.players) {
playerCount++;
}
if ( (joinTime+30000 < endTime) && (playerCount >= 4) && (playerCount <= 8) ) { //check we didn't join in the last 30 seconds of the game, and there was between 4-8 players
gameData.mapName = mapName;
gameData.mapAuthor = mapAuthor;
gameData.gameMode = mapType;
gameData.playerCount = playerCount;
if (tagpro.serverHost === null) tagpro.serverHost = document.URL.replace('http://', '').replace(/:(.*)/, '');
if (tagpro.serverHost.startsWith('tagpro-')) {
gameData.serverName = capitaliseFirstLetter(tagpro.serverHost.replace('tagpro-', '').replace('.koalabeast.com', ''));
} else {
gameData.serverName = document.URL.replace('http://', '').replace(/:(.*)/, '');
}
gameData.played = new Date(joinTime).toISOString();
gameData.timePlayed = playedGameLength;
gameData.fullGameLength = fullGameLength;
gameData.team = tagpro.players[tagpro.playerId].team;
gameData.redScore = tagpro.score.r;
gameData.blueScore = tagpro.score.b;
gameData.saved = 0;
if (data.winner === 'tie') {
gameData.outcome = 5; //tie
} else if ( ((data.winner === 'red') && (tagpro.players[tagpro.playerId].team === 1)) || ((data.winner === 'blue') && (tagpro.players[tagpro.playerId].team === 2)) ) {
gameData.outcome = 1; //win
if (saveAttempt) {
gameData.saved = 2; //successful save attempt
}
} else if ( ((data.winner === 'red') && (tagpro.players[tagpro.playerId].team === 2)) || ((data.winner === 'blue') && (tagpro.players[tagpro.playerId].team === 1)) ) {
if (saveAttempt) {
gameData.outcome = 4; //unsuccessful save attempt
gameData.saved = 1;
} else {
gameData.outcome = 2; //loss
}
} else { //probably an event, which we won't record...
return false;
}
gameData.tags = tagpro.players[tagpro.playerId]["s-tags"];
gameData.pops = tagpro.players[tagpro.playerId]["s-pops"];
gameData.grabs = tagpro.players[tagpro.playerId]["s-grabs"];
gameData.drops = tagpro.players[tagpro.playerId]["s-drops"];
gameData.hold = tagpro.players[tagpro.playerId]["s-hold"];
gameData.captures = tagpro.players[tagpro.playerId]["s-captures"];
gameData.prevent = tagpro.players[tagpro.playerId]["s-prevent"];
gameData.returns = tagpro.players[tagpro.playerId]["s-returns"];
gameData.support = tagpro.players[tagpro.playerId]["s-support"];
gameData.powerups = tagpro.players[tagpro.playerId]["s-powerups"];
gameData.score = tagpro.players[tagpro.playerId].score;
gameData.points = tagpro.players[tagpro.playerId].points;
gameData.potentialPowerups = pupsCount * Math.ceil(playedGameLength / 60); //is this right???
//save scoreboard...
gameData.playersData = [];
for (playerId in tagpro.players) {
gameData.playersData.push({
name:tagpro.players[playerId].name,
us:(tagpro.playerId === tagpro.players[playerId].id ? true : false),
id:tagpro.players[playerId].id,
team:tagpro.players[playerId].team,
auth:tagpro.players[playerId].auth,
tags:tagpro.players[playerId]["s-tags"],
pops:tagpro.players[playerId]["s-pops"],
grabs:tagpro.players[playerId]["s-grabs"],
drops:tagpro.players[playerId]["s-drops"],
hold:tagpro.players[playerId]["s-hold"],
captures:tagpro.players[playerId]["s-captures"],
prevent:tagpro.players[playerId]["s-prevent"],
returns:tagpro.players[playerId]["s-returns"],
support:tagpro.players[playerId]["s-support"],
powerups:tagpro.players[playerId]["s-powerups"],
score:tagpro.players[playerId].score,
points:tagpro.players[playerId].points
});
}
gameData.playersData.sort(function(a, b) {
return (b.score - a.score ? b.score - a.score : a.id - b.id);
});
O300_Selections.O300SavedGames.value.push(gameData);
GM_setValue('O300_Selections', O300_Selections);
}
}
});
}
});
//Get things ready and start the script...
O300_Selections = $.extend(true, {}, options, GM_getValue('O300_Selections', options));
GM_setValue('O300_Selections', O300_Selections);
$.each(O300_Selections, function(key, value) {
O300_Selections[key].type = options[key].type;
if (key !== 'O300SavedGames') {
O300_Selections[key].display = options[key].display;
if ((key !== 'O300MainPages') && (key !== 'O300HeaderPages')) {
O300_Selections[key].title = options[key].title;
}
}
});
//Setup the main div location depending on which page we are on...
var O300_Div = '<div id="O300" style="position:relative; margin:20px auto 0 auto; padding:10px; width:fit-content; font:12px Arial; color:#fff; text-align:center; text-shadow:2px 1px 2px #000000; border-radius:8px; ' + (O300_Selections.ShowBoxShadowBorder.value ? 'box-shadow:#fff 0px 0px 10px; ' : '') + 'background:rgba(0,0,0,0.1); white-space:nowrap;">' +
'<div style="display:inline-block; background:orange; font-size:14px; color:white; padding:3px 10px; margin:3px 0; border-radius:5px;">Stats OFF Rolling 300 Timeline</div>' +
'<div id="O300_Settings_Button" style="display:inline-block; font:10px Arial; text-align:center; margin-left:10px; height:13px; width:13px; border:2px solid #3A8CBB; border-radius:8px; cursor:pointer" title="Options">&#8286;</div>' +
'</div>';
//Header div...
var WinP_Div = '<div id="O300_WinNextHeader" style="position:relative; width:100%; top:1px; font:12px Arial;font-weight:bold; color:#fff; text-align:center; text-shadow:1px 2px 1px #222; clear:both"><span style="background:orange; color:white; padding:0px 5px; margin:0px 10px; border-radius:4px;" title="This is the Stats OFF version of the R300 script. It will try and record the data whether your stats are on or off.">Stats OFF</span></div>';
//Chosen server page...
if (PageLoc === 'server') {
$uHome.append(O300_Div);
$uHome.removeClass('hidden');
$('#O300').append('<div id="O300_loading" style="margin:20px; font-size:18px; color:#ff0">Getting Data...<div style="background:#000000 url(\'https://i.imgur.com/WKZPcQA.gif\') no-repeat center; margin-top:10px; opacity:0.7; height:64px; width:100%;"></div></div>');
if (O300_Selections.O300HeaderPages.title.indexOf('Home') >= 0) {
$('body').prepend(WinP_Div);
}
//Profile page...
} else if (PageLoc === 'profile') {
if (O300_Selections.O300MainPages.title.indexOf('Profile') >= 0) {
$uBottom.append(O300_Div);
$uBottom.removeClass('hidden');
}
if (O300_Selections.O300HeaderPages.title.indexOf('Profile') >= 0) {
$('body').prepend(WinP_Div);
}
//Joining page...
} else if (PageLoc === 'joining') {
if (O300_Selections.O300MainPages.title.indexOf('Joiner') >= 0) {
$uBottom.append(O300_Div);
$uBottom.removeClass('hidden');
}
if (O300_Selections.O300HeaderPages.title.indexOf('Joiner') >= 0) {
$('body').prepend(WinP_Div);
}
//In A Game...
} else if (PageLoc === 'ingame') {
if (O300_Selections.O300HeaderPages.title.indexOf('Game') >= 0) {
$('body').prepend(WinP_Div);
}
}
if ($('#O300').length) {
$('#O300').append('<div id="O300_InnerContainer" style="display:none"></div>');
$('#O300_InnerContainer').append('<div id="O300_Intervals"></div>');
$('#O300_InnerContainer').append('<div id="O300_Timeline"></div>');
$('#O300_InnerContainer').append('<div id="O300_MessagesPie" style="display:flex; align-items:center; justify-content:center;"></div>');
$('#O300_InnerContainer').append('<div id="O300_GameInfo" style="position:absolute; display:none; padding:5px; text-align:center; font-size:10px; background:#050544; color:wheat; border-radius:5px; box-shadow:0px 0px 10px; z-index:100"></div>');
$('#O300_MessagesPie').append('<div id="O300_Messages" style="flex:0 0 auto; align-self:flex-start;"></div>');
$('#O300_MessagesPie').append('<div id="O300_Trimmed" style="display:none; flex:0 0 auto; margin:0 0 0 20px; padding:4px; border:1px solid #aaa; border-radius:3px; font-size:11px; box-shadow:1px 1px 5px white;"></div>');
$('#O300_Trimmed').append('<div id="O300T_Timeline" style="padding:0"></div>');
$('#O300_Trimmed').append('<div id="O300T_Messages"></div>');
} else if ($('#O300_WinNextHeader').length) {
$('#O300_WinNextHeader').append('<div id="O300_GameInfo" style="position:absolute; display:none; padding:5px; text-align:center; font-size:10px; background:#050544; color:wheat; border-radius:5px; box-shadow:0px 0px 10px; z-index:100"></div>');
}
var $O300_Timeline = $('#O300_Timeline');
var $O300_Messages = $('#O300_Messages');
var $O300T_Timeline = $('#O300T_Timeline');
var $O300T_Messages = $('#O300T_Messages');
GM_addStyle('#O300_GameInfo table { text-align:center; line-height:8px; border-collapse:collapse }');
GM_addStyle("#O300_GameInfo tr.O300_GameInfo_HighlightSelf { background:rgba(255,255,255,0.2); }");
GM_addStyle('#O300_GameInfo td { border:1px solid grey; padding:2px 4px; }');
GM_addStyle('.O300_RedTeamColor { color:#F8B0B8; font-weight:normal }');
GM_addStyle('.O300_BlueTeamColor { color:#C9C9F8; font-weight:normal }');
GM_addStyle('#O300_GameInfoScoreboard .O300_Max { color:darkorange }');
GM_addStyle('#O300_Stats { margin:10px auto; font-size:11px; color:#bbb; line-height:9px; text-align:center; font-style:normal; border-collapse:collapse; border-spacing:1px; cursor:default }');
GM_addStyle('#O300_Stats th { border:1px solid #555; color:#ddd; background:#334; font-weight:normal; width:40px }');
GM_addStyle('#O300_Stats td { border:1px solid #555; }');
GM_addStyle('#O300T_Stats { margin:10px auto; font-size:9px; color:#bbb; line-height:9px; text-align:center; font-style:normal; border-collapse:collapse; border-spacing:1px; cursor:default }');
GM_addStyle('#O300T_Stats th { border:1px solid #555; color:#ddd; background:#334; font-weight:normal; }');
GM_addStyle('#O300T_Stats td { border:1px solid #555; }');
if (O300_Selections.ShowO300MapStats.value) {
GM_addStyle("#O300_MS_Data_Table { margin:0 auto; line-height:10px; text-align:center; cursor:default; border-collapse:collapse }");
GM_addStyle("#O300_MS_Data_Table td { border:1px solid grey; padding:1px 2px }");
GM_addStyle("#O300_MS_Data_Table th { border:1px solid grey; padding:1px 2px; font-size:11px; color:#ddd; background:#666 }");
GM_addStyle("#O300_MS_Data_Table th:hover { text-decoration:underline }");
GM_addStyle("#O300_MS_Data_Table tbody tr:hover { color:#0bb }");
GM_addStyle("#O300_MS_Data_Table .O300_MS_MapName { color:#ddd; background:#666; text-align:right }");
GM_addStyle("#O300_MS_Data_Table .O300_MS_35 { min-width:35px; max-width:35px; overflow:hidden }");
GM_addStyle("#O300_MS_Data_Table .O300_MS_50 { min-width:50px; max-width:50px; overflow:hidden }");
GM_addStyle("#O300_MS_Data_Table .O300_MS_60 { min-width:60px; max-width:60px; overflow:hidden }");
GM_addStyle("#O300_MS_Data_Table .O300_MS_90 { min-width:90px; max-width:90px; overflow:hidden }");
GM_addStyle('#O300_MS_Data_Table tbody::-webkit-scrollbar { width:3px }');
GM_addStyle('#O300_MS_Data_Table tbody::-webkit-scrollbar-thumb { background:cornflowerblue; }');
GM_addStyle('#O300_MS_Data_Table tbody::-webkit-scrollbar-track { background:#ddd; }');
}
if (O300_Selections.ShowO300ASBP.value) {
GM_addStyle("#O300_ASBP_Data_Table { width:400px; margin:0 auto; line-height:10px; text-align:center; cursor:default; border-collapse:collapse }");
GM_addStyle("#O300_ASBP_Data_Table td { border:1px solid grey; padding:1px 2px; min-width:30px; max-width:30px; overflow:hidden }");
GM_addStyle("#O300_ASBP_Data_Table th { border:1px solid grey; padding:1px 2px; color:#ccc; background:#666; min-width:30px; max-width:30px; overflow:hidden }");
GM_addStyle("#O300_ASBP_Data_Table th:hover { text-decoration:underline }");
GM_addStyle("#O300_ASBP_Data_Table tbody tr:hover { color:#0bb }");
GM_addStyle("#O300_ASBP_Data_Table .O300_ASBP_PlayerName { color:#ccc; background:#666; text-align:right; min-width:100px; max-width:100px; overflow:hidden }");
GM_addStyle("#O300_ASBP_Data_Table .O300_ASBP_HighlightSelf { color:#cc0 }");
GM_addStyle('#O300_ASBP_Data_Table tbody::-webkit-scrollbar { width:3px }');
GM_addStyle('#O300_ASBP_Data_Table tbody::-webkit-scrollbar-thumb { background:salmon; }');
GM_addStyle('#O300_ASBP_Data_Table tbody::-webkit-scrollbar-track { background:#ddd; }');
}
if (O300_Selections.ShowOtherPlayers.value) {
GM_addStyle('#O300_OtherPlayersStats { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; margin:5px auto; font-size:11px; font-family:monospace; }');
GM_addStyle('.O300_OtherPlayerStats { position:relative; color:#bbb; background:rgba(50,50,100,0.1); margin:4px; padding:2px 10px; border:1px solid #888; border-radius:5px; cursor:default }');
GM_addStyle('.O300_OtherPlayerStats:hover { color:white; background:rgba(0,0,100,0.5); border:1px solid white }');
GM_addStyle('#O300_OtherPlayersStats_Add { color:chartreuse; font-size:14px; padding:5px; border:1px dashed #888; border-radius:5px; }');
GM_addStyle('#O300_OtherPlayersStats_Add:hover { background:rgba(127,255,0,0.3); border:1px solid chartreuse; cursor:pointer }');
GM_addStyle('.O300_OtherPlayerStats_Remove { position:absolute; width:9px; height:8px; font-size:9px; color:#600; top:1px; right:1px; text-shadow:none; border:1px solid #600; border-radius:5px; }');
GM_addStyle('.O300_OtherPlayerStats_Remove:hover { color:#f00; border:1px solid #f00; background:rgba(255,0,0,0.3); cursor:pointer }');
GM_addStyle('#O300_OtherPlayersStats_Sortby { margin-left:5px; width:20px; height:20px; font-size:11px; color:#600; background:bisque; border-radius:5px; }');
GM_addStyle('.O300_OtherPlayerName { font-size:12px; text-decoration:underline; color:#fff }');
GM_addStyle('.O300_OtherPlayerName:hover { color:dodgerblue }');
GM_addStyle('.O300_OtherPlayer_HighlightToday { color:skyblue }');
GM_addStyle('@keyframes rotateText { from { transform:rotate(0deg); } to { transform:rotate(360deg); } }');
GM_addStyle('.O300_RotateAddText { animation:rotateText 2s linear infinite; display:inline-block;}');
}
if ( $('#O300').length || $('#O300_WinNextHeader').length ) {
$(window).load(function() { //we need this otherwise somethings won't draw if the page hasn't finished rendering
loadData();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment