Skip to content

Instantly share code, notes, and snippets.

@dot-mike
Last active December 11, 2016 02:51
Show Gist options
  • Save dot-mike/7a0d80c459f94dcd3d63b12f885d0f96 to your computer and use it in GitHub Desktop.
Save dot-mike/7a0d80c459f94dcd3d63b12f885d0f96 to your computer and use it in GitHub Desktop.
/**
* Advanced Scoreboard
*
* @author Cr1N
* @version 1.0.1
*/
BBLog.handle("add.plugin", {
/* Plugin Infos */
id : "bf4-advanced-scoreboard-plugin-dev-1-0",
name : "Advanced Scoreboard",
version : '1.0',
build: '20141216',
/* Plugin load */
init : function(instance)
{
//Store the path at initizliation
instance.data.currentPath = location.pathname;
instance.debug("Plugin Initialized on path " + location.pathname);
if ( location.pathname.match(new RegExp("^/bf4/(|[a-z]{2}/)(servers|serverbrowserwarsaw)/show/pc/.*","i")) )
{
instance.debug("Server paged detected, initializing main handler");
instance.handler(instance);
}
},
domchange : function(instance) {
if( location.pathname !== instance.data.currentPath )
{
instance.debug("Changed path from " + instance.data.currentPath + ' to ' + location.pathname);
if( instance.data.pluginLoaded )
{
instance.debug("Calling plugin unload func");
instance.unloadPlugin(instance); //URL has changed, unload the plugin.
}
instance.data.currentPath = location.pathname;
console.log("Path Changed: " + location.pathname);
if( location.pathname.match(new RegExp("^/bf4/(|[a-z]{2}/)(servers|serverbrowserwarsaw)/show/pc/.*","i")) )
{
instance.debug("Calling main handler");
$(document).ready(function()
{
instance.handler(instance);
})
}
} else {
console.log("Path did not change on domchange");
$(document).ready(function () {
if (instance.data.pluginLoaded && $("#live-header").is(":visible")) {
console.log("Plugin is loaded though, scoreboard not initialised...");
instance.unloadPlugin(instance); //URL has changed, unload the plugin.
instance.handler(instance);
}
})
}
},
data: {
advancedViewPlayer : 0, //Persona ID of player to show advanced statistics for
animationActive : false,
asLiveUpdate : false,
asTrackerUpdate : false,
charts : {"skillDistribution" : false, "tickets" : false,},
currentChart : false,
currentPath : '',
drawMode: "player",
gameServerWarsaw : gamedatawarsaw.function_warsawgameserver(),
latestScoreboardData: {}, //Holds the most recently retrieved set of scoreboard data to present unneccessary requests
mode: 'scoreboard', //Mode of the plugin
onServerPage : false,
pluginLoaded: false,
tracker : {"tickets" : {}, "kills" : {},}, //Track various aspects of the round over time
updateIntervalMs : 5000,
},
//Holds player statistics
playerStats : {},
translations:
{
"en":
{
"settings-title" : "Settings",
},
"de":
{
"settings-title" : "Einstellungen",
}
},
/* Main handler */
handler : function(instance) {
instance.debug("Handler Executed");
console.log(Surface.globalContext);
//Clear any previous tickers
instance.data.asLiveUpdate = false;
instance.data.pluginLoaded = true;
//Check if this is the first plugin return
//instance.storage('isConfigured', false);
if(!instance.storage('isConfigured')) { //If not run before, this will return false
instance.debug('Initial setup!')
instance.storage('hilightingEnabled', true);
instance.storage('liveEnabled', true);
instance.storage('displayStat', 'kdRatio');
instance.storage('isConfigured', true);
instance.storage('hilightFriends', true);
instance.storage('liveTracking', false);
instance.storage('sortAttribute', "score");
instance.storage('sortMode', "desc");
instance.storage('useResetKdr', false);
instance.storage('pollingIntervalMs', 5000);
alert("Configuration Parameters Successfully Set");
}
//Charting is disabled in this version...
///Add the custom css
//$('head').append('<link rel="stylesheet" href="http://indiangamingleagues.com/i242clan/blog_plugin/main/c3.css" type="text/css" />');
$('head').append('<link rel="stylesheet" href="https://aa9de85e6af703e53a9804a161a1197964182874.googledrive.com/host/0Bx16wo_LcoPLfkw3a3R4bmNOMEdyQzlqN0c2N3VBVUJLak5GSnVmRERFUk9VeXplUFlLZ0E/advanced_scoreboard.css" type="text/css" />');
//Load charting library - disabled
/*
$.ajax({
url: 'http://indiangamingleagues.com/i242clan/blog_plugin/main/d3.min.js',
success: instance.debug("Loaded D3"),
dataType: "script",
cache: true
});
$.ajax({
url: 'http://indiangamingleagues.com/i242clan/blog_plugin/main/c3.min.js',
success: instance.debug("Loaded C3"),
dataType: "script",
cache: true
});
*/
//Load items library from battlelog if not present
if (!window.items) {
instance.debug("Loading items library")
var path = "/public/gamedatawarsaw/warsaw.items.js";
var loadedLib = $.ajax(
{
type: "GET",
dataType: "script",
url: base.asset(path),
cache: true
});
} else {
instance.debug("Items Library already present!")
}
//Hide the server info
//$("#server-page-details div").hide();
//Hide the default scoreboard and insert wrapper DIV for custom scoreboard
$("#server-players-list").hide();
$("#serverbrowser-page").after('<div id="as-container"></div>');
var roundInfoHeader = instance.drawRoundInfo(instance);
$("#as-container").html(roundInfoHeader);
var selectors = instance.drawSelectors(instance);
$("#as-container").append(selectors);
$("#as-container").append('<div id="as-scoreboard-container"></div>');
console.log("Okay, instance.storage");
var settingsLog = "Current configuration:<br /><br/>";
settingsLog += 'Hilighting : ' + instance.storage('hilightingEnabled') + "<br/>" +
'Live Updates : ' + instance.storage('liveEnabled') + "<br />" +
'Displayed Stat : ' + instance.storage('displayStat') + "<br />" +
'Live Tracking : ' + instance.storage('liveTracking') + "<br />" +
'Sorting Attribute : ' + instance.storage('sortAttribute') + "<br />" +
'Sorting Mode : ' + instance.storage('sortMode') + "<br />" +
'Allow Reset Stats : ' + instance.storage('useResetKdr') + "<br />" +
'Configuration flag : ' + instance.storage('isConfigured') + "<br />" +
'Tickrate : ' + instance.storage('pollingIntervalMs') + "<br/>";
console.log(BBLog._storage[instance.id + '.pollingIntervalMs']);
//Draw settings/config box
//instance.renderSettings(instance);
//Create scoreboard from data
instance.updateAll(instance);
//Charting
//instance.drawCharts(instance);
//Live update interval
if (instance.storage('liveEnabled')) {
instance.data.asLiveUpdate = setInterval(function () {
instance.updateAll(instance);
}, 5000);
instance.debug("Live update started by main handler")
} else {
instance.debug("Live update disabled");
}
/** EVENT HANDLERS **/
//Scoreboard
//Settings
//Change player view
$("#as-show-squads").click(function () {
instance.data.drawMode = "squad";
instance.updateHTML(instance);
instance.debug("Switched drawing mode to Squad");
});
//Handler for selector hilighting
$(".view-selector").click(function ()
{
$(".view-selector").removeClass("btn-primary");
$(this).addClass("btn-primary");
});
//Handler for clicking on a player row
$("#as-container").on('click', '.as-player', function()
{
var personaId = $(this).attr('personaid');
instance.debug("Player row has been clicked: " + personaId);
var thisRow = $(this);
if($(this).hasClass('as-advanced-stats-selected'))
{
instance.data.advancedViewPlayer = false;
instance.data.animationActive = true;
$(".as-advanced-player-view").slideUp("fast", function()
{
$(".as-scoreboard-advanced-stats-row").remove();
$(".as-advanced-stats-selected").removeClass("as-advanced-stats-selected");
instance.data.animationActive = false;
});
return;
}
var existingRows = $(".as-scoreboard-advanced-stats-row");
//Remove all instances
if( existingRows.length > 0 )
{
var attRows = $(".as-advanced-stats-selected");
$(".as-advanced-player-view").slideUp("fast", function()
{
console.log("Slid up");
existingRows.remove();
attRows.removeClass("as-advanced-stats-selected");
});
instance.data.advancedViewPlayer = personaId;
var html = instance.createAdvancedPlayerView(instance, personaId, false);
console.log(html);
thisRow.addClass('as-advanced-stats-selected').after(html);
instance.data.animationActive = true;
$(".as-advanced-player-view").slideDown("fast", function()
{
instance.data.animationActive = false;
});
} else {
instance.data.advancedViewPlayer = personaId;
var html = instance.createAdvancedPlayerView(instance, personaId, false);
$(this).addClass('as-advanced-stats-selected').after(html);
instance.data.animationActive = true;
$(".as-advanced-player-view").slideDown("fast", function()
{
instance.data.animationActive = false;
});
}
});
//Handler for clicking a role title and expanding the top players
$("#as-container").on('click', '.as-role-title-row', function () {
console.log("Clicked role title row");
var roleRow = $(this).next("tr").find(".as-role-top-players");
if( roleRow.is(":visible") )
{
roleRow.slideUp("fast");
} else {
roleRow.slideDown("fast");
}
});
//Handler for clicking the player join button
$("#as-container").on('click', '#as-ao-join', function(){
var personaId = $(this).attr('persona-id');
instance.joinPlayer(personaId);
})
$("#as-container").on('click', '#as-ao-radar', function()
{
if ( $("div.as-ao-confirm").is(":visible")) {
return;
}
var personaId = $(this).attr("persona-id");
var radarSoldiers = BBLog._storage["radar.soldier"];
var isPresent = false;
if (radarSoldiers) {
for (var i = 0; i < radarSoldiers.length; i++) {
if (radarSoldiers[i]['id'] == personaId) {
isPresent = true;
}
}
}
if (!isPresent) {
var html = '<div class="as-ao-confirm"><span>Add to radar?</span><button id="as-ao-radar-yes">Yes</button><button id="as-ao-radar-no">No</button></div>';
} else {
var html = '<div class="as-ao-confirm"><span>Remove from radar?</span><button id="as-ao-remove-yes">Yes</button><button id="as-ao-radar-no">No</button></div>';
}
$(this).parent().after(html);
instance.data.animationActive = true;
$(".as-ao-confirm").slideDown('fast');
});
$("#as-container").on('click', '#as-ao-radar-yes', function () {
var parent = $(this).parent();
var personaId = $("#as-ao-radar").attr("persona-id");
var name = $("#as-ao-name").html();
if (name.split("]").length > 1) {
name = name.split("]")[1];
}
var radarSoldier = {
id: personaId,
name: name,
source: 'bf4'
}
if (!BBLog._storage["radar.soldier"]) {
BBLog._storage["radar.soldier"] = [];
}
var radarSoldiers = BBLog._storage["radar.soldier"];
BBLog._storage["radar.soldier"].push(radarSoldier);
parent.slideUp('fast', function () {
instance.data.animationActive = false;
parent.remove();
instance.updateHTML(instance);
});
});
$("#as-container").on('click', '#as-ao-remove-yes', function () {
var personaId = $("#as-ao-radar").attr("persona-id");
var name = $("#as-ao-name").html();
if (name.split("]").length > 1) {
name = name.split("]")[1];
}
var radarSoldiers = BBLog._storage["radar.soldier"];
for (var i = 0; i < radarSoldiers.length; i++) {
if (radarSoldiers[i]['id'] == personaId) {
radarSoldiers.splice(i, 1);
}
}
$(".as-ao-confirm").slideUp('fast', function () {
$(".as-ao-confirm").remove();
instance.data.animationActive = false;
instance.updateHTML(instance);
});
});
$("#as-container").on('click', '#as-ao-radar-no', function () {
var parent = $(this).parent();
parent.slideUp('fast', function () {
parent.remove();
instance.data.animationActive = false;
instance.updateHTML(instance);
});
});
$("#as-container").on('click', '#as-show-squads', function () {
instance.data.drawMode = "squad";
instance.updateHTML(instance);
});
$("#as-container").on('click', '#as-show-players', function () {
instance.data.drawMode = "player";
instance.updateHTML(instance);
});
$("#as-container").on('click', '#as-show-roles', function () {
instance.data.drawMode = "role";
instance.updateHTML(instance);
});
$("#as-container").on('click', '#as-show-charts', function () {
alert("Charts disabled for now.");
});
$("#as-container").on('click', '#as-settings', function () {
instance.data.drawMode = "settings";
instance.drawSettings(instance);
});
$("#as-container").on('click', '#as-quit-game', function () {
var game = gamemanager.gameState.game;
console.log("Quitting game " + game);
gamemanager._killGame(gamemanager.gameState.game);
});
//Handler for showing the advanced stats window
$("#as-container").on('click', '#as-ao-advanced', function () {
//instance.data.mode = 'stats';
//instance.drawAdvancedStats(instance, $(this).attr('persona-id'));
//Test animations
var overview = $(this).parent().parent().parent();
var slideUp = $(".as-scoreboard-wrapper").slideUp('slow');
$.when(slideUp).done(function () {
$("#as-scoreboard-container").html(overview.html());
})
});
//Handler for hiding the stats window
$("#server-page").on('click', '.as-stats-close', function () {
$("#as-stats-container").animate({
opacity: 0,
height: 'toggle'
},
1000, function ()
{
$("#as-stats-container").remove();
instance.data.mode = 'scoreboard';
instance.data.animationActive = true;
$("#as-container").animate({
opacity: 1,
height: 'toggle'
}, 1000, function ()
{
instance.data.animationActive = false;
instance.updateHTML(instance);
});
$('html, body').animate({ scrollTop: $("#as-scoreboard-container").offset().top }, 1000);
});
});
//Settings
//Event handler for the display stat select menu
$("#as-select-display-stat").on('change', function(){
instance.storage('displayStat', this.value);
instance.updateHTML(instance);
});
$("#content").on('click', '#as-settings-close', function ()
{
$("#as-settings-container").remove();
})
//Sorting event handlers
$("#as-container").on('click', '.as-scoreboard-head td', function()
{
var elem = $(this);
if( elem.hasClass("sort-desc") )
{
console.log("has sort-desc")
elem.removeClass("sort-desc").addClass("sort-asc");
instance.storage('sortMode', 'asc' );
}
else if( elem.hasClass("sort-asc") )
{
console.log("has sort-asc")
elem.removeClass("sort-asc").addClass("sort-desc");
instance.storage('sortMode', 'desc' );
}
else
{
console.log("unclassed")
elem.addClass("sort-desc");
instance.storage('sortMode', 'desc');
}
instance.storage('sortAttribute', this.getAttribute("sort"));
instance.updateHTML(instance);
});
//Event handler for hilighting checkbox
$("#as-container").on('change', '#as-enable-hilighting', function(){
if(this.checked) {
instance.storage('hilightingEnabled', true);
} else {
instance.storage('hilightingEnabled', false);
}
instance.updateHTML(instance);
});
//Event handler for friend hilighting
$("#as-enable-friend-hilighting").change(function(){
if(this.checked) {
instance.storage('hilightingEnabled', true);
} else {
instance.storage('hilightingEnabled', false);
}
instance.updateHTML(instance);
});
//Scroll right in the advanced view
//Event handler for the live update checkbox
$("#content").on('change', '#as-enable-live', function()
{
if(this.checked) {
instance.storage('liveEnabled', true);
if(!instance.data.asLiveUpdate) {
instance.data.asLiveUpdate = setInterval(function(){
instance.updateAll(instance);
}, 5000);
instance.updateAll(instance);
instance.debug("Live update started via event handler")
}
} else {
instance.storage('liveEnabled', false);
if(instance.data.asLiveUpdate) {
clearInterval(instance.data.asLiveUpdate);
instance.data.asLiveUpdate = false;
instance.debug("Live update stopped")
}
}
})
//Stats
$("#server-page").on('click', '.as-stats-select-weapons', function ()
{
$(".as-stats-vehicles").slideUp('fast', function () {
$(".as-stats-weapons").slideDown('fast');
});
});
$("#server-page").on('click', '.as-stats-select-vehicles', function () {
$(".as-stats-weapons").slideUp('fast', function () {
$(".as-stats-vehicles").slideDown('fast');
});
});
//Join on a specific team
$("#as-container").on('click', '.join-team', function () {
var teamId = $(this).attr('team-id');
//alert("I want to join " + teamId);
var teams = instance.data.latestScoreboardData.teams;
var team = {};
for (var i = 0; i < teams.length; i++) {
if(teams[i].status.teamId == teamId) {
team = teams[i];
break;
}
}
//Iterate team and find lowest ranked played
var lowestRank = 140;
var lowestPlayer = {};
for (var i = 0; i < team.players.length; i++) {
var player = team.players[i];
if (player.rank < lowestRank) {
lowestRank = player.rank;
lowestPlayer = player;
}
}
console.log("The team is:")
console.log(team);
console.log("The player is:");
console.log(lowestPlayer);
console.log("Okay latest data is:")
console.log(team);
instance.joinPlayer(lowestPlayer.personaId);
});
$("#as-render-scorboard-button").click(function(){
instance.updateAll(instance);
});
},
/**
* Allows the user to join the server on any player regardless of if they are on your friends list
*
* @param personaId The Battlelog Persona ID of the player to join
*
*/
joinPlayer : function(personaId)
{
var elem = document.getElementById("server-page-join-buttons");
var guid = elem.getAttribute("data-guid");
var platform = elem.getAttribute("data-platform");
var game = elem.getAttribute("data-game");
window.gamemanager.joinServerByGuid(guid, platform, game, personaId, 1);
},
drawCharts : function(instance)
{
//Disabled
return false;
instance.debug("Okay, drawing charts...");
//Create a div to hold the test chart
if($("#as-scoreboard-container").is(':visible')) {
$("#as-scoreboard-container").html('<div id="as-charting-container"></div>')
} else { //Catch issue with navigation
instance.unloadPlugin(instance);
instance.handler(instance);
}
//Put tracking data into array
var chartData = [];
for( var dataSet in instance.data.tracker.tickets )
{
var data = instance.data.tracker.tickets[dataSet];
instance.debug(data);
chartData.push(data);
}
/*
instance.data.currentChart = c3.generate({
bindto: '#as-charting-container',
data: {
columns: chartData
},
type: 'spline'
});
*/
instance.debug("Here's the player stats");
instance.debug(instance.playerStats);
instance.debug("Here's the scoreboardData");
instance.debug(instance.data.latestScoreboardData);
//Okay get the latest scoreboarddata
var teamPlot = [];
var teamNames = {};
for(var team in instance.data.latestScoreboardData.teams)
{
var teamObject = instance.data.latestScoreboardData.teams[team];
var teamName = instance.lookup.teamName(instance.data.latestScoreboardData.gameMode, teamObject.status);
var skillStats = [teamName + ' skill'];
var kdStats = [teamName + ' kd'];
for (var player in teamObject.players)
{
instance.debug("Looping player in sbdata players");
var playerObject = teamObject.players[player];
var personaId = playerObject.personaId;
skillStats.push(instance.playerStats[personaId].overviewStats.skill);
kdStats.push(instance.playerStats[personaId].overviewStats.kdRatio);
}
teamPlot.push(skillStats, kdStats);
teamNames[teamName + " skill"] = teamName + ' kd';
}
instance.debug(teamPlot);
instance.data.charts.skillDistribution = c3.generate({
bindto: '#as-charting-container',
data : {
xs: teamNames,
columns: teamPlot,
type: 'scatter'
},
axis: {
x: {
label: 'KD Ratio',
min: 0,
tick: {
fit: false,
centered: true
}
},
y: {
label: 'Skill',
min: 0,
},
},
tooltip: {
format: {
title: function (d) { return 'Data' + teamNames[0]; },
}
},
})
},
/**
* Refreshes all data and redraws scoreboard
*
* @param instance Plugin object instance
*
*/
updateAll : function(instance){
var serverInfo = instance.getServerAttributes(); // Server attributes
instance.queryServerScoreboard(serverInfo, function(queryResult)
{
instance.debug(queryResult);
//Store the result of the query
instance.data.latestScoreboardData = queryResult;
//Cache player statistics
instance.updatePlayerStats(instance, queryResult);
//Render the scoreboard with this data
if( !instance.data.animationActive && instance.data.mode == 'scoreboard' )
{
if( instance.data.drawMode == "player" ) {
instance.drawPlayerScoreBoard(instance, queryResult);
}
else if ( instance.data.drawMode == "squad" ) {
instance.drawSquadScoreBoard(instance, queryResult); // Draw the scoreboard using the query result
} else if ( instance.data.drawMode == "role" ) {
instance.drawRoleScoreBoard(instance, queryResult);
}
else if ( instance.data.drawMode == "charts" ) {
instance.updateTracker(instance, queryResult, function(instance)
{
instance.updateCharts(instance);
});
}
}
//Update the round header
instance.updateRoundHeader(instance, queryResult);
});
},
/**
* Redraws HTML without refreshing data sources
*
* @param instance Plugin object instance
*
*/
updateHTML : function(instance) {
if(!instance.data.animationActive && instance.data.mode == 'scoreboard')
{
if(instance.data.drawMode == "player")
{
instance.drawPlayerScoreBoard(instance, instance.data.latestScoreboardData);
} else if ( instance.data.drawMode == "role" ) {
instance.drawRoleScoreBoard(instance, instance.data.latestScoreboardData);
} else if (instance.data.drawMode == "squad") {
instance.drawSquadScoreBoard(instance, instance.data.latestScoreboardData); // Draw the scoreboard using the query result
}
}
},
/**
* Updates the tracking object with data from the server
*
* @param instance Plugin object instance
* @param serverData Data from the server
* @param callback Callback function
*/
updateTracker : function(instance, serverData, callback)
{
for(i = 0; i < serverData.teams.length; i++)
{
var team = serverData.teams[i];
var teamId = team.status.teamId;
var tickets = team.status.tickets;
if( instance.data.tracker.tickets.hasOwnProperty(teamId) )
{
instance.data.tracker.tickets[teamId].push(tickets);
}
else
{
instance.data.tracker.tickets[teamId] = [instance.lookup.teamName(serverData.gameMode, team.status), tickets];
}
}
instance.debug(instance.data.tracker);
callback(instance);
},
/**
* Updates the charts
*
* @param instance Plugin object instance
*/
updateCharts : function(instance)
{
if( instance.data.currentChart ) {
var chartData = [];
for( var dataSet in instance.data.tracker.tickets )
{
var data = instance.data.tracker.tickets[dataSet];
instance.debug(data);
chartData.push(data);
}
instance.data.currentChart.load({
columns : chartData
});
}
},
/**
* Returns an object containing the team data for the round and the total stats for each team
*
* @param instance Plugin Object Instance
* @param scoreboardData JSON Object containing the information received from the gameserver
*/
calculateTeamTotals : function(instance, scoreboardData)
{
var s = scoreboardData;
console.log("Gimme commander feature pls");
console.log(s);
var teams = [];
$.each(s.teams, function(teamID, team)
{
var players = team.players;
var status = team.status;
var teamObj = {
'players' : [],
'status' : team.status,
'totalPlayers' : 0,
'totalRank' : 0,
'totalKills' : 0,
'totalDeaths' : 0,
'totalScore' : 0,
'playersLoaded' : 0,
'totalPDisplayStat': 0,
'commander': false
};
$.each(team.players, function(playerId, player)
{
var playerObj =
{
'id': player.personaId,
'tag': player.tag,
'name': player.name,
'rank': player.rank,
'role': player.role,
'squad': player.squad,
'score': player.score,
'kills': player.kills,
'deaths': player.deaths,
'kd': (player.deaths == 0) ? player.kills : player.kills / player.deaths,
'statsLoaded' : false,
'pDisplayStat': 0
}
if (player.role == 2) {
console.log("COMMANDER FOUND!");
console.log(player);
teamObj.commander = playerObj;
} else {
teamObj.totalRank += player.rank;
teamObj.totalKills += player.kills;
teamObj.totalDeaths += player.deaths;
teamObj.totalScore += player.score;
teamObj.totalPlayers++;
//Load the players statistics from the
if (instance.playerStats.hasOwnProperty(player.personaId)) {
playerObj.statsLoaded = true;
var pStats = instance.playerStats[player.personaId];
var displayStat = instance.storage('displayStat');
if (displayStat == 'kdRatio' && !instance.storage('useResetKdr')) {
if (pStats.overviewStats.deaths == 0) {
playerObj.pDisplayStat = pStats.overviewStats.kills
} else {
playerObj.pDisplayStat = Math.round((pStats.overviewStats.kills / pStats.overviewStats.deaths) * 100) / 100;
}
} else if (displayStat == 'strength') {
var strength = (pStats.overviewStats.skill * pStats.overviewStats.kdRatio * pStats.overviewStats.killsPerMinute * pStats.overviewStats.scorePerMinute) / 1000;
playerObj.pDisplayStat = Math.floor(strength);
} else {
playerObj.pDisplayStat = pStats.overviewStats[displayStat];
}
teamObj.totalPDisplayStat += playerObj.pDisplayStat;
teamObj.playersLoaded++;
}
teamObj.players.push(playerObj);
}
})
teams.push(teamObj);
})
return teams;
},
/**
* Returns an object detailing the role specializations of the team. i.e. top players by vehicle type/weapon type
*
* @param instance Plugin Object Instance
* @param scoreboardData JSON Object cotnaining the information received from the gameserver
*/
calculateRoles: function(instance, scoreboardData)
{
var start = new Date().getTime();
var s = scoreboardData;
var teamRoles = [];
instance.debug("Starting roles calc");
$.each(s.teams, function(teamId, team)
{
var players = team.players;
var status = team.status;
var commander = false;
var vehicles = {};
$.each(players, function(playerId, player)
{
//If the user's overviewstats have been loaded
if( instance.playerStats.hasOwnProperty(player.personaId) ) {
var pStats = instance.playerStats[player.personaId];
//Iterate over the top play vehicles and add them to the role totals for the team
for (var i = 0; i < pStats.topVehicles.length; i++) {
var vehicle = pStats.topVehicles[i];
var vehicleName = vehicle.category.replace('Vehicle ', '');
if (vehicle.kills > 100) {
if ( vehicles.hasOwnProperty(vehicleName) ) {
var playerPresent = false;
//Check if player already exists in this category, e.g. AH6-J kills logged under scout category, but Z-11 have not yet been processed
for (var j = 0; j < vehicles[vehicleName].topPlayers.length; j++) {
if (vehicles[vehicleName].topPlayers[j].personaId == player.personaId) {
playerPresent = true;
vehicles[vehicleName].topPlayers[j].kills += vehicle.kills;
vehicles[vehicleName].topPlayers[j].time += vehicle.timeIn;
break;
}
}
if (!playerPresent) {
var playerVehicleStats = {
personaId: player.personaId,
kills: vehicle.kills,
rank: player.rank,
time: vehicle.time
}
vehicles[vehicleName].topPlayers.push(playerVehicleStats);
}
vehicles[vehicleName].totalKills += vehicle.kills;
vehicles[vehicleName].totalTime += vehicle.timeIn;
} else {
vehicles[vehicleName] = {
topPlayers: [],
totalKills: 0,
totalTime: 0,
};
var playerVehicleStats = {
personaId: player.personaId,
kills: vehicle.kills,
rank: player.rank,
time: vehicle.time
}
vehicles[vehicleName].totalKills += vehicle.kills;
vehicles[vehicleName].totalTime += vehicle.timeIn;
vehicles[vehicleName].topPlayers.push(playerVehicleStats);
var vehicleDisplay = window.items.game_data.compact.vehicles[vehicle.guid]
vehicleDisplay = vehicleDisplay.see[0];
var lineartSlug = window.items.game_data.compact.vehicles[vehicleDisplay];
lineartSlug = lineartSlug.imageConfig.slug;
if (!vehicles[vehicleName].lineartSlug) {
vehicles[vehicleName].lineart = lineartSlug;
}
}
}
}
console.log(pStats);
}
});
teamRoles.push(vehicles);
});
var end = new Date().getTime();
var time = end - start;
console.log("Calculating roles took " + time + "ms");
return teamRoles;
},
/**
* A refactored version of the scoreboard rendering function to allow for more flexible output and design
*
* @param instance Plugin Object Instance
* @param s JSON Object containing the information received from the gameserver
*/
drawPlayerScoreBoard : function(instance, scoreboardData)
{
instance.debug('Drawing player scoreboard');
var start = new Date().getTime();
var s = scoreboardData;
var teams = instance.calculateTeamTotals(instance, scoreboardData);
instance.debug('Here are the team totals:')
instance.debug(teams);
//Disabled, fixed next version
/* Load in the BBLog radar and check if any of the players on the server match
if (BBLog._storage["radar.soldier"]) {
var radar = BBLog._storage["radar.soldier"];
}
else {
var radar = false;
}
var radarSoldiers = [];
if (radar) {
for (var i = 0; i < radar.length; i++) {
var radarSoldier = radar[i];
radarSoldiers[radarSoldier.id] = true;
}
}
*/
//We now have our custom teams object with all the relevant information
var html = "";
//Iterate over each team
for( i = 0; i < teams.length; i++ )
{
var team = teams[i];
var teamName = instance.lookup.teamName(s.gameMode, team.status);
var teamFlag = instance.lookup.teamFlag(teamName);
//Create wrapper and table for team
html += '<div class="as-scoreboard-wrapper" teamId = "' + team.status.teamId + '">' +
'<table class="table as-scoreboard-table" teamId="' + team.status.teamId + '">' +
'<thead><tr class="as-scoreboard-details">' +
'<td colspan="7"><span style="vertical-align: top; display: inline-block; margin: 5px; bottom: 5px;">';
var progressBarWidth = Math.floor((team.status.tickets/team.status.ticketsMax) * 100);
var progressBar ='<div class="progress-bar thicker no-border '+instance.lookup.teamType(team.status.teamId)+'" style="position: relative; display: inline-block; width: 100px; margin: 5px;"><div class="home progress-bar-inner" style="width:'+progressBarWidth+'%"></div></div>';
//html += '<thead><tr class="as-scoreboard-details"><td colspan="7"><span style="vertical-align: top; display: inline-block; margin: 5px; bottom: 5px;">';
if ( teamFlag ) {
html += '<img alt="flag" class="as-team-flag" src="' + teamFlag + '"></img>';
}
html += teamName + ' : ' + team.status.tickets +
'</span>' + progressBar +
'<span style="vertical-align: top; display: inline-block; margin: 5px; bottom: 5px;">Players: [' + team.players.length + '/' + (s.maxPlayers/2).toFixed(0) + ']</span>' +
'<button class="btn join-team" team-id="' + team.status.teamId + '">Join</button>' +
'</td>';
//HTML for table header
html += '<tr class="as-scoreboard-head">'//<td sort="rank">Rank</td><td sort="name">Name</td><td sort="kills">K</td><td sort="deaths">D</td><td sort="score" class="sort-desc">Score</td><td sort="kd">K/D</td><td sort="pDisplayStat">' + instance.lookup.displayStat(instance.storage('displayStat')) +'</td></tr></thead>';
var columns = [
{header : "Rank", sortAttribute : "rank"},
{header : "Name", sortAttribute : "name"},
{header : "K", sortAttribute : "kills"},
{header : "D", sortAttribute : "deaths"},
{header : "Score", sortAttribute : "score"},
{header : "K/D", sortAttribute : "kd"},
{header : instance.lookup.displayStat(instance.storage('displayStat')), sortAttribute : "pDisplayStat"}
]
var sortAttribute = instance.storage('sortAttribute');
var sortMode = instance.storage('sortMode');
for( j = 0; j < columns.length; j++)
{
var column = columns[j];
html += '<td ' + (column.sortAttribute == sortAttribute ? 'class="sort-' + sortMode + '"' : '') +' sort="' + column.sortAttribute + '">' + column.header + (column.sortAttribute == sortAttribute ? '<div class="sort-' + sortMode + '"></div>' : '') + '</td>';
}
html += '</tr></thead>';
//Here we decide the order in which players will be displayed..
team.players.sort(function (a, b) {
if (sortMode == 'desc') {
return a[sortAttribute] == b[sortAttribute] ? 0 : +(a[sortAttribute] < b[sortAttribute]) || -1;
} else {
return a[sortAttribute] == b[sortAttribute] ? 0 : +(a[sortAttribute] > b[sortAttribute]) || -1;
}
});
//Iterate over the players on the team and create a table row for them
for( j = 0; j < team.players.length; j++ ) {
var player = team.players[j];
//Rank display html
var pRank = '<div class="bf4-rank rank small r' + player.rank + ' rank_icon" data-rank="' + player.rank +'"></div>'
//Player name including tags
var pName = player.tag.length > 0 ? '[' + player.tag + ']' + player.name : player.name;
pName = '<a href="/bf4/user/' + player.name + '/">' + pName + '</a>';
//Player K/D
var pKD = player.deaths == 0 ? player.kills : player.kills/player.deaths;
//Set hilighting class
var hilightingType = false;
if (instance.storage('hilightingEnabled') && player.statsLoaded) {
hilightingType = instance.lookup.hilightingClass(instance.storage('displayStat'), player.pDisplayStat);
}
/*
if( radarSoldiers.hasOwnProperty(player.id)) {
hilightingType += " radar"
}
*/
var friends = comcenter.getFriendsListFromLs();
var isFriend = false;
for ( var k = 0; k < friends.length; k++ )
{
if(friends[k].username == player.name) {
isFriend = true;
break;
}
}
var displayStat = player.statsLoaded ? player.pDisplayStat : '<div class="loader small"></div>';
//Generate table row
html += '<tr class="as-player' + (player.id == instance.data.advancedViewPlayer ? ' as-advanced-stats-selected' : '') + (isFriend ? ' friend' : '') + (hilightingType ? ' ' + hilightingType : '') + '" personaid="' + player.id + '"><td>' + pRank + '</td><td>' + pName + '</td><td>' + player.kills + '</td><td>' + player.deaths + '</td><td>' + player.score +'</td><td>' + pKD.toFixed(2) + '</td><td>' + displayStat + '</td></tr>'
//If a specific player is selected for the advanced view, inject the HTML here
if (player.id == instance.data.advancedViewPlayer ) {
html += instance.createAdvancedPlayerView(instance, player.id, true);
}
}
/*** Create tfoot from averages ***/
//Average rank display html
var avgRank = '<div class="bf4-rank rank small r' + Math.floor(team.totalRank/team.players.length) + ' rank_icon" data-rank="' + Math.floor(team.totalRank/team.players.length) +'"></div>'
//Average KD
var avgKD = team.totalDeaths == 0 ? team.totalKills : team.totalKills/team.totalDeaths;
//Average pDisplayStat
var avgpDisplayStat = team.totalPDisplayStat == 0 ? '...' : (team.totalPDisplayStat/team.playersLoaded).toFixed(2);
//HTML for scoreboard foot
html += '<tfoot><tr class="as-scoreboard-foot"><td>'+ avgRank +'</td><td></td><td>'+ team.totalKills +'</td><td>' + team.totalDeaths + '</td><td>' + team.totalScore +'</td><td>' + avgKD.toFixed(2) + '</td><td>' + avgpDisplayStat + '</td></tr></tfoot>';
html += '</table>';
if (team.commander) {
var commander = team.commander;
var cRank = '<div class="bf4-rank rank small r' + commander.rank + ' rank_icon" data-rank="' + commander.rank + '"></div>'
var cKd = commander.deaths == 0 ? commander.kills : commander.kills / commander.deaths;
//Player name including tags
var cName = commander.tag.length > 0 ? '[' + commander.tag + ']' + commander.name : commander.name;
pName = '<a href="/bf4/user/' + commander.name + '/">' + cName + '</a>';
html += '<table class="table as-commander-scoreboard"><tbody><tr><td>' + cRank + '</td><td>' + cName + '</td><td>' + commander.kills + '</td><td>' + commander.deaths + '</td><td>' + commander.score + '</td><td>' + cKd + '</td><td>' + commander.pDisplayStat + '</td></tr></tbody></table>';
}
html += '</div>';
}
console.log("Update Log:");
console.log(s);
console.log(instance.data.gameServerWarsaw.mapLookup);
//Update the map name
var displayMap = '<img class="current-map" src="//eaassets-a.akamaihd.net/bl-cdn/cdnprefix/9c0b010cd947f38bf5e87df5e82af64e0ffdc12fh/public/base/bf4/map_images/195x79/' + s.mapName.toLowerCase() + '.jpg"></img>' +
'<div id="as-map-name">' + instance.data.gameServerWarsaw.mapLookup[s.mapName].label + '</div>' +
'<div id="as-map-mode">' + instance.lookup.gameMode(s.gameMode) + '</div>';
$("#as-scoreboard-mapinfo").html(displayMap);
var serverInfo = '<table class="as-server-properties">' +
'<tr><th>Players</th><td>' + + '</td></tr>' +
'</table>';
$("#as-round-properties").html(serverInfo);
var defaultRoundtimeSeconds = 3600;
var currentRoundTime = 3600 * (s.defaultRoundTimeMultiplier/100);
var expiredTime = s.roundTime;
var secondsRemaining = currentRoundTime - expiredTime;
var timeLeft = Math.floor(secondsRemaining/60) + 'M ' + (Math.round((secondsRemaining%60) * 100)/100) + 'S';
$("span#as-server-time-remaining").html(timeLeft)
//HTML For the round status
var totalPlayers = 0;
for (var i = 0; i < s.teams.length; i++) {
var team = s.teams[i];
totalPlayers += team.players.length;
}
var roundProperties = '<table class="as-round-properties">' +
'<tr><td>Players</td><td>' + totalPlayers + '/' + s.maxPlayers + (s.queueingPlayers > 0 ? '[' + s.queueingPlayers + ']' : '') + '</td></tr>' +
'</table>';
$("#as-scoreboard-round-properties").html(roundProperties)
if ($("#as-scoreboard-container").is(':visible')) {
$("#as-scoreboard-container").html(html)
} else { //Catch issue with navigation
instance.unloadPlugin(instance);
instance.handler(instance);
}
var end = new Date().getTime();
var time = end - start;
console.log("Drawing took " + time + "msg");
},
drawSquadScoreBoard : function(instance, scoreboardData)
{
var start = new Date().getTime();
instance.debug('Beginning render process for squad view');
var s = scoreboardData;
var teams = instance.calculateTeamTotals(instance, scoreboardData);
console.log(teams);
html = "";
for(var i = 0; i < teams.length; i++)
{
var team = teams[i];
var teamName = instance.lookup.teamName(s.gameMode, team.status);
var teamFlag = instance.lookup.teamFlag(teamName);
instance.debug("Drawing team " + i)
var squads = {}; //Squads object
var squadNames = [];
//Sort the team players into squads, and calculate their respective totals
for(j = 0; j < team.players.length; j++)
{
var player = team.players[j];
var playerSquadName = instance.lookup.squadName(player.squad);
if(squads.hasOwnProperty(instance.lookup.squadName(player.squad)))
{
squads[playerSquadName].players.push(player);
}
else
{
squadNames.push(playerSquadName);
squads[playerSquadName] = {};
squads[playerSquadName]["rank"] = 0;
squads[playerSquadName]["kills"] = 0;
squads[playerSquadName]["deaths"] = 0;
squads[playerSquadName]["score"] = 0;
squads[playerSquadName]["sTotal"] = 0;
squads[playerSquadName]["players"] = [];
squads[playerSquadName].players.push(player);
}
//Add player stats to squad total
squads[playerSquadName]["kills"] += player.kills;
squads[playerSquadName]["deaths"] += player.deaths;
squads[playerSquadName]["score"] += player.score;
squads[playerSquadName]["rank"] += player.rank;
if(instance.playerStats.hasOwnProperty(player.id)) {
var pStats = instance.playerStats[player.id];
var pDisplayStat = pStats.overviewStats[instance.storage('displayStat')];
squads[playerSquadName]["sTotal"] += pDisplayStat;
}
}
console.log(squads);
html += '<div class="as-scoreboard-wrapper" teamId = "' + team.status.teamId + '"><table class="table as-scoreboard-table" teamId="' + team.status.teamId + '">';
//Progress bar HTML for GFX representation of tickets
var progressBarWidth = Math.floor((team.status.tickets/team.status.ticketsMax) * 100);
var progressBar ='<div class="progress-bar thicker no-border '+instance.lookup.teamType(team.status.teamId)+'" style="position: relative; display: inline-block; width: 100px; margin: 5px;"><div class="home progress-bar-inner" style="width:'+progressBarWidth+'%"></div></div>';
html += '<thead><tr class="as-scoreboard-details"><td colspan="7"><span style="vertical-align: top; display: inline-block; margin: 5px; bottom: 5px;">';
if (teamFlag) {
html += '<img alt="flag" class="as-team-flag" src="' + teamFlag + '"></img>';
}
html += teamName + ' : ' + team.status.tickets +
'</span>' + progressBar +
'<span style="vertical-align: top; display: inline-block; margin: 5px; bottom: 5px;">Players: [' + team.players.length + '/' + (s.maxPlayers / 2).toFixed(0) + ']</span></td>';
//HTML for table header
//html += '<tr class="as-scoreboard-head"><td>Rank</td><td>Name</td><td>K</td><td>D</td><td>Score</td><td>K/D</td><td>' + instance.lookup.displayStat(instance.storage('displayStat')) +'</td></tr></thead>';
//Sort the array of squadnames alphabeticaly
squadNames.sort();
for (var j = 0; j < squadNames.length; j++)
{
var squadName = squadNames[j];
var squad = squads[squadName];
var sKD = squad.deaths == 0 ? squad.kills : squad.kills/squad.deaths;
//html += '<tr class="spacer"><td colspan="7"></td></tr>';
html += '<tr class="as-squad-row"><td colspan="7">' + squadName.toUpperCase() + ' [' + squad.players.length + '/5]</td/></tr>';
for(var k = 0; k < squad.players.length; k++)
{
var player = squad.players[k];
var pRank = '<div class="bf4-rank rank small r' + player.rank + ' rank_icon" data-rank="' + player.rank +'"></div>';
var pName = player.tag.length > 0 ? '[' + player.tag + ']' + player.name : player.name;
var pKD = player.deaths == 0 ? player.kills : player.kills/player.deaths;
var hilightingType = false;
if( instance.storage('hilightingEnabled') && pDisplayStat !== '...' ) {
if(instance.storage('displayStat') == 'kdRatio') {
if(player.pDisplayStat < 1) {
hilightingType = 'low';
} else if(player.pDisplayStat < 2) {
hilightingType = 'average';
} else if(player.pDisplayStat < 3) {
hilightingType = 'good';
} else if(player.pDisplayStat < 4) {
hilightingType = 'high';
} else if(player.pDisplayStat >= 4) {
hilightingType = 'v-high';
}
} else if(instance.storage('displayStat') == 'skill') {
if(player.pDisplayStat < 200) {
hilightingType = 'low';
} else if(player.pDisplayStat < 300) {
hilightingType = 'average';
} else if(player.pDisplayStat < 400) {
hilightingType = 'good';
} else if(player.pDisplayStat < 550) {
hilightingType = 'high';
} else if(player.pDisplayStat >= 550) {
hilightingType = 'v-high';
}
}
}
//Generate table row
html += '<tr class="as-player' + (player.id == instance.data.advancedViewPlayer ? ' as-advanced-stats-selected' : '') + (isFriend ? ' friend' : '') + (hilightingType ? ' ' + hilightingType : '') + '" personaid="' + player.id + '"><td>' + pRank + '</td><td>' + pName + '</td><td>' + player.kills + '</td><td>' + player.deaths + '</td><td>' + player.score +'</td><td>' + pKD.toFixed(2) + '</td><td>' + player.pDisplayStat + '</td></tr>';
if (player.id == instance.data.advancedViewPlayer) {
instance.debug("Creating advanced player view");
html += instance.createAdvancedPlayerView(instance, player.id, true);
}
var friends = comcenter.getFriendsListFromLs();
var isFriend = false;
for (var l = 0; l < friends.length; l++)
{
if(friends[i].username == player.name)
{
isFriend = true;
break;
}
}
}
var avgSquadRank = Math.floor(squad.rank / squad.players.length);
var avgRank = '<div class="bf4-rank rank small r' + avgSquadRank + ' rank_icon" data-rank="' + avgSquadRank + '"></div>';
html += '<tr class="as-squad-summary"><td>' + avgRank + '<td></td><td>' + squad.kills + '</td><td>' + squad.deaths + '</td><td>' + squad.score + '</td><td>' + sKD.toFixed(2) + '</td><td>' + (squad.sTotal / squad.players.length).toFixed(2) + '</td></tr>';
for(var k = squad.players.length; k < 5; k++)
{
html += '<tr class="as-squad-spacer"><td colspan="7"></td></tr>';
}
}
/*** Create tfoot from averages ***/
//Average rank display html
var avgRank = '<div class="bf4-rank rank small r' + Math.floor(team.totalRank/team.totalPlayers) + ' rank_icon" data-rank="' + Math.floor(team.totalRank/team.totalPlayers) +'"></div>'
//Average KD
var avgKD = team.totalDeaths == 0 ? team.totalKills : team.totalKills/team.totalDeaths;
//Average pDisplayStat
var avgpDisplayStat = team.totalPDisplayStat == 0 ? '...' : (team.totalPDisplayStat/team.playersLoaded).toFixed(2);
//HTML for scoreboard foot
//html += '<tfoot><tr class="as-scoreboard-foot"><td>'+ avgRank +'</td><td></td><td>'+ team.totalKills +'</td><td>' + team.totalDeaths + '</td><td>' + team.totalScore +'</td><td>' + avgKD.toFixed(2) + '</td><td>' + avgpDisplayStat + '</td></tr></tfoot>';
html += '</table>'
html += '</div>';
}
if($("#as-scoreboard-container").is(':visible')) {
$("#as-scoreboard-container").html(html)
} else { //Catch issue with navigation
instance.unloadPlugin(instance);
instance.handler(instance);
}
},
drawRoleScoreBoard : function(instance, scoreboardData)
{
var start = new Date().getTime();
instance.debug("Beginning render process for role scoreboard");
var s = scoreboardData;
console.log("Calculating role data for both teams")
var vehicleRoles = instance.calculateRoles(instance, s);
console.log("Role Data:");
console.log(vehicleRoles);
console.log("Calculating team data");
var teams = instance.calculateTeamTotals(instance, scoreboardData);
console.log("Team data:");
console.log(teams);
//We now have our custom teams object with all the relevant information
var html = "";
//Iterate by vehicle type
for (i = 0; i < vehicleRoles.length; i++) {
var teamVehicleRoles = vehicleRoles[i];
var team = teams[i];
var teamName = instance.lookup.teamName(s.gameMode, team.status);
var teamFlag = instance.lookup.teamFlag(teamName);
//Players lookup object
var teamPlayers = {};
for (var playerId in team.players) {
var player = team.players[playerId];
teamPlayers[player.id] = player;
}
console.log("Here is team:");
console.log(team);
html += '<div class="as-scoreboard-wrapper" teamId = "' + team.status.teamId + '"><table class="table as-scoreboard-table" teamId="' + team.status.teamId + '">';
var progressBarWidth = Math.floor((team.status.tickets / team.status.ticketsMax) * 100);
var progressBar = '<div class="progress-bar thicker no-border ' + instance.lookup.teamType(team.status.teamId) + '" style="position: relative; display: inline-block; width: 100px; margin: 5px;"><div class="home progress-bar-inner" style="width:' + progressBarWidth + '%"></div></div>';
html += '<thead>' +
'<tr class="as-scoreboard-details"><td colspan="7"><span style="vertical-align: top; display: inline-block; margin: 5px; bottom: 5px;">' +
'<img alt="flag" class="as-team-flag" src="' + teamFlag + '"></img>' + teamName + ' : ' + team.status.tickets +
'</span>' + progressBar +
'<span style="vertical-align: top; display: inline-block; margin: 5px; bottom: 5px;">Players: [' + team.players.length + '/' + (s.maxPlayers / 2).toFixed(0) + ']</span></td></tr></thead>';
for (var vehicleRole in teamVehicleRoles) {
var vehicle = teamVehicleRoles[vehicleRole];
console.log("Vehicle is here:")
console.log(vehicle);
//Sort by top players
vehicle.topPlayers.sort(function (a, b) {
return a.kills == b.kills ? 0 : +(a.kills < b.kills) || -1;
});
html += '<tr class="as-role-title-row"><td class="as-role-title" colspan="7"><div class="as-role-title-text">' + vehicleRole + '</div><div class="vehicle small ' + vehicle.lineart + ' image"></div></td></tr>';
html += '<tr><td colspan="7" style="padding: 0px;"><div class="as-role-top-players"><table style="width:100%; border: 0px;">';
for (var key in vehicle.topPlayers) {
var topPlayer = vehicle.topPlayers[key];
var personaId = topPlayer.personaId;
var kills = topPlayer.kills;
var playerStats = teamPlayers[personaId];
console.log(playerStats);
if(!playerStats)
continue;
var pRank = '<div class="bf4-rank rank small r' + playerStats.rank + ' rank_icon" data-rank="' + playerStats.rank + '"></div>'
//Player name including tags
var pName = playerStats.tag.length > 0 ? '[' + playerStats.tag + ']' + playerStats.name : playerStats.name;
pName = '<a href="/bf4/user/' + playerStats.name + '/">' + pName + '</a>';
//Player K/D
var pKD = playerStats.deaths == 0 ? playerStats.kills : playerStats.kills / playerStats.deaths;
//Set hilighting class
var hilightingType = false;
if (instance.storage('hilightingEnabled')) {
hilightingType = instance.lookup.hilightingClass(instance.storage('displayStat'), playerStats.pDisplayStat);
}
var friends = comcenter.getFriendsListFromLs();
var isFriend = false;
for (var k = 0; k < friends.length; k++) {
if (friends[k].username == player.name) {
isFriend = true;
break;
}
}
html += '<tr class="as-player' + (playerStats.id == instance.data.advancedViewPlayer ? ' as-advanced-stats-selected' : '') + (isFriend ? ' friend' : '') + (hilightingType ? ' ' + hilightingType : '') + '" personaid="' + playerStats.id + '"><td>' + pRank + '</td><td>' + pName + '</td><td>' + playerStats.kills + '</td><td>' + playerStats.deaths + '</td><td>' + playerStats.score + '</td><td>' + pKD.toFixed(2) + '</td><td>' + topPlayer.kills + '</td></tr>'
//If a specific player is selected for the advanced view, inject the HTML here
if (playerStats.id == instance.data.advancedViewPlayer) {
instance.debug("Creating advanced player view");
html += instance.createAdvancedPlayerView(instance, playerStats.id, true);
}
}
html += '</table></div></td></tr>'
}
html += '</table></div>'
}
//Iterate over each team
for (i = teams.length; i < teams.length; i++)
{
var team = teams[i]; //The team
var teamVehicles = vehicleRoles[i];
var teamName = instance.lookup.teamName(s.gameMode, team.status);
var teamFlag = instance.lookup.teamFlag(teamName);
//Create wrapper and table for team
html += '<div class="as-scoreboard-wrapper" teamId = "' + team.status.teamId + '"><table class="table as-scoreboard-table" teamId="' + team.status.teamId + '">'
var progressBarWidth = Math.floor((team.status.tickets / team.status.ticketsMax) * 100);
var progressBar = '<div class="progress-bar thicker no-border ' + instance.lookup.teamType(team.status.teamId) + '" style="position: relative; display: inline-block; width: 100px; margin: 5px;"><div class="home progress-bar-inner" style="width:' + progressBarWidth + '%"></div></div>';
html += '<thead>' +
'<tr class="as-scoreboard-details"><td colspan="7"><span style="vertical-align: top; display: inline-block; margin: 5px; bottom: 5px;">' +
'<img alt="flag" class="as-team-flag" src="' + teamFlag + '"></img>' + teamName + ' : ' + team.status.tickets +
'</span>' + progressBar +
'<span style="vertical-align: top; display: inline-block; margin: 5px; bottom: 5px;">Players: [' + team.players.length + '/' + (s.maxPlayers / 2).toFixed(0) + ']</span></td></tr></thead>';
//HTML for table header
console.log("The team:");
console.log(team);
var playerLookup = {};
for (var j = 0; j < team.players.length; j++)
{
playerLookup[team.players[j].id] = team.players[j];
}
console.log("Player Lookup:");
console.log(playerLookup);
//Output players
console.log("Team vehicles:");
console.log(teamVehicles);
for (var k in teamVehicles) {
var vehiclePlayers = teamVehicles[k].topPlayers;
var vehicle = teamVehicles[k];
console.log("Vehicle players");
console.log(teamVehicles);
//Sort vehicle players
vehiclePlayers.sort(function (a, b) {
return a.kills == b.kills ? 0 : +(a.kills < b.kills) || -1;
});
console.log("Okay, vehicle shit:");
console.log(teamVehicles);
html += '<tr class="as-role-title-row"><td class="as-role-title" colspan="7"><div class="as-role-title-text">' + k + '</div><div class="vehicle small '+ vehicle.lineart + ' image"></div></td></tr>';
html += '<tr><td colspan="7" style="padding: 0px;"><div class="as-role-top-players"><table style="width:100%; border: 0px;">';
//For each player in that category
for (var l in vehiclePlayers) {
console.log("VehiclePlayers");
console.log(vehiclePlayers)
var player = playerLookup[vehiclePlayers[l].personaId];
console.log("PlayerLookup:");
console.log(playerLookup);
console.log("Player");
console.log(player);
console.log("playerLookup");
console.log(playerLookup);
console.log("vehiclePlayers[l].personaId");
console.log(vehiclePlayers[l].personaId);
var vehiclePlayer = vehiclePlayers[l];
console.log("The Vehicle Player:");
console.log(vehiclePlayer);
//Rank display html
var pRank = '<div class="bf4-rank rank small r' + vehiclePlayer.rank + ' rank_icon" data-rank="' + vehiclePlayer.rank + '"></div>'
//Player name including tags
var pName = player.tag.length > 0 ? '[' + player.tag + ']' + player.name : player.name;
pName = '<a href="/bf4/user/' + player.name + '/">' + pName + '</a>';
//Player K/D
var pKD = player.deaths == 0 ? player.kills : player.kills / player.deaths;
//Set hilighting class
var hilightingType = false;
if (instance.storage('hilightingEnabled')) {
hilightingType = instance.lookup.hilightingClass(instance.storage('displayStat'), player.pDisplayStat);
}
var friends = comcenter.getFriendsListFromLs();
var isFriend = false;
for (var k = 0; k < friends.length; k++) {
if (friends[k].username == player.name) {
isFriend = true;
break;
}
}
//Generate table row
html += '<tr class="as-player' + (player.id == instance.data.advancedViewPlayer ? ' as-advanced-stats-selected' : '') + (isFriend ? ' friend' : '') + (hilightingType ? ' ' + hilightingType : '') + '" personaid="' + player.id + '"><td>' + pRank + '</td><td>' + pName + '</td><td>' + player.kills + '</td><td>' + player.deaths + '</td><td>' + player.score + '</td><td>' + pKD.toFixed(2) + '</td><td>' + vehiclePlayer.kills + '</td></tr>'
//If a specific player is selected for the advanced view, inject the HTML here
if (player.id == instance.data.advancedViewPlayer) {
instance.debug("Creating advanced player view");
html += instance.createAdvancedPlayerView(instance, player.id, true);
}
}
html += '</table></div></td></tr>';
}
/*** Create tfoot from averages ***/
//Average rank display html
var avgRank = '<div class="bf4-rank rank small r' + Math.floor(team.totalRank / team.players.length) + ' rank_icon" data-rank="' + Math.floor(team.totalRank / team.players.length) + '"></div>'
//Average KD
var avgKD = team.totalDeaths == 0 ? team.totalKills : team.totalKills / team.totalDeaths;
//Average pDisplayStat
var avgpDisplayStat = team.totalPDisplayStat == 0 ? '...' : (team.totalPDisplayStat / team.playersLoaded).toFixed(2);
//HTML for scoreboard foot
html += '<tfoot><tr class="as-scoreboard-foot"><td>' + avgRank + '</td><td></td><td>' + team.totalKills + '</td><td>' + team.totalDeaths + '</td><td>' + team.totalScore + '</td><td>' + avgKD.toFixed(2) + '</td><td>' + avgpDisplayStat + '</td></tr></tfoot>';
html += '</table>'
html += '</div>';
}
//Update the map name
var displayMap = '<img class="current-map" src="//eaassets-a.akamaihd.net/bl-cdn/cdnprefix/9c0b010cd947f38bf5e87df5e82af64e0ffdc12fh/public/base/bf4/map_images/195x79/' + s.mapName.toLowerCase() + '.jpg"></img><br><span>' + instance.data.gameServerWarsaw.mapLookup[s.mapName].label + '</span>';
$("#as-scoreboard-mapinfo").html(displayMap);
var defaultRoundtimeSeconds = 3600;
var currentRoundTime = 3600 * (s.defaultRoundTimeMultiplier / 100);
var expiredTime = s.roundTime;
var secondsRemaining = currentRoundTime - expiredTime;
var timeLeft = Math.floor(secondsRemaining / 60) + 'M ' + (Math.round((secondsRemaining % 60) * 100) / 100) + 'S';
$("span#as-time-remaining").html(timeLeft)
if ($("#as-scoreboard-container").is(':visible')) {
$("#as-scoreboard-container").html(html)
} else { //Catch issue with navigation
instance.unloadPlugin(instance);
instance.handler(instance);
}
var end = new Date().getTime();
var time = end - start;
console.log("Role Scoreboard took " + time + "ms");
},
//Updates the round header
updateRoundHeader : function(instance, s)
{
var totalPlayers = 0;
console.log("updating header");
console.log(s);
for (var i = 0; i < s.teams.length; i++)
{
var team = s.teams[i];
totalPlayers += team.players.length;
}
$("#as-server-players").html(totalPlayers + '/' + s.maxPlayers + (s.queueingPlayers > 0 ? '[' + s.queueingPlayers + ']' : ''));
},
/**
* Creates the HTML for the advanced player view, detailing the soldiers statistics
*
*
*
*/
createAdvancedPlayerView : function(instance, personaId, displayDefault){
instance.debug(instance.playerStats);
var html = '<tr class="as-scoreboard-advanced-stats-row"><td colspan="7">' +
'<div class="as-advanced-player-view"' + (displayDefault ? '' : ' style="display:none"') +'>'
//Ensure statistics are present locally
if(!instance.playerStats.hasOwnProperty(personaId)) {
html += '<div class="loader small"></div></div></td></tr>'
} else {
//Create stats overview here
var pStats = instance.playerStats[personaId];
var playerName = pStats.name;
var timePlayed = pStats.overviewStats.timePlayed;
var timePlayedHours = (timePlayed/60)/60;
var timePlayedMinutes = (timePlayedHours - Math.floor(timePlayedHours)) * 60;
if (pStats.activeEmblem) {
var emblemPath = pStats.activeEmblem.cdnUrl;
emblemPath = emblemPath.replace('[SIZE]', '128');
emblemPath = emblemPath.replace('[FORMAT]', 'png');
}
//Player name, gravatar, and emblem
html += '<div class="as-ao-header"><span id="as-ao-name">' + pStats.name + (pStats.activeEmblem ? '</span><img class="as-ao-emblem" src="' + emblemPath + '"></img>' : '') +
'<button id="as-ao-join" persona-id="' + personaId + '" class="as-ao-btn btn">Join</button>' +
'<button id="as-ao-advanced" persona-id="' + personaId + '" class="as-ao-btn btn">Advanced</button>' +
'</div>';
//Top kits
var topKits = '<table class="table as-advanced-overview-top-kits">' +
'<tr><th><div class="kit-icon xsmall kit-1"></div></th><th><div class="kit-icon xsmall kit-2"></div></th><th><div class="kit-icon xsmall kit-32"></div></th><th><div class="kit-icon xsmall kit-8"></div></th></tr>' +
'<tr><td>' + pStats.overviewStats.serviceStars["1"] + '</td><td>' + pStats.overviewStats.serviceStars["2"] + '</td><td>' + pStats.overviewStats.serviceStars["32"] + '</td><td>' + pStats.overviewStats.serviceStars["8"] + '</td>' +
'</table>';
//Stats overviewhttp://battlelog.battlefield.com/bf4/platoons/view/3353238464465530114/
console.log(pStats);
//Viewport
html += '<div class="as-ao-view">';
html += '<div class="as-ao-stats">';
html += '<div class="as-advanced-overview-top-stats">' +
'<table class="table as-advanced-overview-top-stats">' +
'<tr><th>Kills</th><th>Deaths</td><th>Skill</td><th>Accuracy</td></tr>' +
'<tr><td>' + instance.commaFormat(pStats.overviewStats.kills) + '</td><td>' + instance.commaFormat(pStats.overviewStats.deaths) + '</td><td>' + pStats.overviewStats.skill + '</td><td>' + pStats.overviewStats.accuracy.toFixed(2) + '%</td></tr>' +
'<tr><th>KPM</th><th>SPM</td><th>KDR</td><th>Time</td></tr>' +
'<tr><td>' + pStats.overviewStats.killsPerMinute + '</td><td>' + pStats.overviewStats.scorePerMinute + '</td><td>' + (pStats.overviewStats.kills/pStats.overviewStats.deaths).toFixed(2) + '</td><td>' + timePlayedHours.toFixed(0) + 'H ' + timePlayedMinutes.toFixed(0) +'M </td></tr>' +
'</table>';
html += topKits;
html += '</div>'
//Overview Stats
//Overview Table
html += '<div class="as-advanced-overview-top-roles">' +
'<table class="table as-advanced-overview-top-vehicles">' +
'<tr><th colspan="2">Vehicle</th><th>Kills</th><th>KPM</th></tr>';
//Top vehicles
$.each(pStats.topVehicles, function (id, vehicle) {
//Get vehicle name for image
var vehicleDisplay = window.items.game_data.compact.vehicles[vehicle.guid];
vehicleDisplay = vehicleDisplay.see[0];
var lineartSlug = window.items.game_data.compact.vehicles[vehicleDisplay];
lineartSlug = lineartSlug.imageConfig.slug;
console.log(vehicle);
html += '<tr><td>' + vehicle.slug.toUpperCase() + '</td><td><div class="vehicle xsmall ' + lineartSlug + ' image"></div></td><td>' + instance.commaFormat(vehicle.kills) + '</td><td>' + (vehicle.kills/(vehicle.timeIn/60)).toFixed(2) + '</td></tr>'
});
html += '</table><table class="table as-advanced-overview-top-weapons">' +
'<tr><th colspan="2">Weapon</th><th>Kills</th><th>Accuracy</th></tr>';
$.each(pStats.topWeapons, function(id, weapon){
//Get vehicle name for image
var weaponDisplay = window.items.game_data.compact.weapons[weapon.guid];
weaponDisplay = weaponDisplay.see[0];
var lineartSlug = window.items.game_data.compact.weapons[weaponDisplay];
lineartSlug = lineartSlug.imageConfig.slug;
html += '<tr><td>' + weapon.slug.toUpperCase() + '</td><td><div class="weapon xsmall ' + lineartSlug + ' image"></div></td><td>' + instance.commaFormat(weapon.kills) + '</td><td>' + ((weapon.shotsHit / weapon.shotsFired) * 100).toFixed(2) + '%</td></tr>'
});
html += '</table></div>';
html += '</div>'
//End of as-ao-stats
//Get Dogtag Information
var dogtagBasic = pStats.dogTagBasic.imageConfig.slug;
var dogtagAdvanced = pStats.dogTagAdvanced.imageConfig.slug;
html += '</div>';
}
//Test for a rough skill calculation
//var skillCalc = (pStats.overviewStats.scorePerMinute * pStats.overviewStats.kdRatio * pStats.overviewStats.killsPerMinute)/100
//html += '<div>' + skillCalc + '</div>';
return html;
},
//Draw the advanced statistics overview
drawAdvancedStats : function (instance, personaId) {
var player = instance.playerStats[personaId];
//Load the players weapon stats
var playerVehicleStats = {};
instance.loadPlayerVehicleStats(personaId, function (data)
{
playerVehicleStats = data.data;
});
var playerWeaponStats = {};
instance.loadPlayerWeaponStats(personaId, function (data) {
playerWeaponStats = data.data;
$("#as-container").fadeOut('slow', function () {
var html = '<div id="as-stats-container">' + '<button class="as-stats-close">Back</button>';
html += '<h3>' + player.name + '</h3>';
html += '<div class="as-stats-selectors"><button class="btn as-stats-select-weapons">Weapons</button><button class="btn as-stats-select-vehicles">Vehicles</button></div>';
//Container to list possible cheating flags
html += '<div class="as-stats-overview">'
html += '<div class="as-stats-weapons">' +
'<table class="table as-stats-weapons-table">';
html += '<tr><th>Weapon</th><th>Kills</th><th>Accuracy</th><th>HSKR</th><th>KPM</th></tr>';
for (var i = 0; i < playerWeaponStats.mainWeaponStats.length; i++)
{
var weapon = playerWeaponStats.mainWeaponStats[i];
if (weapon.kills > 100) {
var weaponDisplay = window.items.game_data.compact.weapons[weapon.guid];
weaponDisplay = weaponDisplay.see[0];
var lineartSlug = window.items.game_data.compact.weapons[weaponDisplay];
lineartSlug = lineartSlug.imageConfig.slug;
var w_accuracy = 0;
if (weapon.shotsFired > 0 && weapon.shotsHit > 0) {
w_accuracy = (weapon.shotsHit / weapon.shotsFired) * 100;
}
var w_kpm = 0;
if (weapon.kills > 0 && weapon.timeEquipped > 0) {
w_kpm = (weapon.kills / (weapon.timeEquipped / 60));
}
var w_hskr = 0;
if (weapon.kills > 0 && weapon.headshots > 0) {
w_hskr = ((weapon.headshots / weapon.kills) * 100);
}
html += '<tr class="as-stats-weapon"><td><div class="weapon xsmall ' + lineartSlug + ' image"></div><div>' + weapon.slug.toUpperCase() + '</div></td><td>' + weapon.kills + '</td><td>' + w_accuracy.toFixed(2) + '%</td><td>' + w_hskr.toFixed(2) + '%</td><td>' + w_kpm.toFixed(2) + '</td></tr>';
console.log(weapon.slug);
console.log(weapon);
}
}
html += '</table></div><div class="as-stats-vehicles" style="display: none;"><table class="table as-stats-vehicles-table">';
html += '<tr><th>Vehicle</th><th>Kills</th><th>Vehicles Destroyed</th><th>KPM</th><th>Time</th></tr>';
console.log(playerVehicleStats);
for (var i = 0; i < playerVehicleStats.mainVehicleStats.length; i++) {
var vehicle = playerVehicleStats.mainVehicleStats[i];
if (vehicle.kills > 100) {
var vehicleDisplay = window.items.game_data.compact.vehicles[vehicle.guid];
vehicleDisplay = vehicleDisplay.see[0];
var lineartSlug = window.items.game_data.compact.vehicles[vehicleDisplay];
lineartSlug = lineartSlug.imageConfig.slug;
var v_vehiclesDestroyed = 0;
if (vehicle.destroyXinY > 0) {
v_vehiclesDestroyed = vehicle.destroyXinY;
}
var v_kpm = 0;
if (vehicle.timeIn > 0 && vehicle.kills > 0)
{
v_kpm = (vehicle.kills / (vehicle.timeIn / 60));
}
var v_time = (vehicle.timeIn / 60).toFixed(2);
html += '<tr class="as-stats-vehicle"><td><div class="vehicle xsmall ' + lineartSlug + ' image"></div><div>' + vehicle.slug.toUpperCase() + '</div></td><td>' + vehicle.kills + '</td><td>' + v_vehiclesDestroyed + '</td><td>' + v_kpm.toFixed(2) + '%</td><td>' + v_time + '</td></tr>';
}
}
html += '</table></div></div>';
$("#serverbrowser-page").after(html);
console.log(playerWeaponStats);
console.log(playerVehicleStats);
});
});
},
drawSettings : function(instance) {
var html = '<div id="as-settings-container"><header class="as-settings-header"><h1>' + instance.t("settings-title") + '</h1></header>' +
'<div id="as-settings-options">';
//Get the settings
console.log(instance.storage('hilightingEnabled'));
var hilightingEnabled = instance.storage('hilightingEnabled') ? (instance.storage('hilightingEnabled') == true ? true : false) : false;
/** Check box for the live update **/
html += '<table class="as-settings-table">' +
'<tr><td class="as-settings-table-header" colspan="3">General</td></tr>' +
'<tr><th>Live Scoreboard</h><td>' +
'<div class="switch-container pull-right clearfix">' +
'<div class="switch pull-left">' +
'<input type="checkbox" id="as-enable-live" name="as-enable-live" value="' + instance.storage('liveEnabled').toString() + '" ' + (instance.storage('liveEnabled') == true ? 'checked' : '') + '>' +
'<div class="handle"></div>' +
'</div>' +
'</div></td>' +
'<td class="option-description">Determines whether or not the scoreboard automatically updates as the game progresses</td>' +
'</tr>' +
'<tr><th>Hilighting</th><td>' +
'<div class="switch-container pull-right clearfix">' +
'<div class="switch pull-left">' +
'<input type="checkbox" id="as-enable-hilighting" name="as-enable-hilighting" value="' + hilightingEnabled.toString() + '" ' + (hilightingEnabled == true ? 'checked' : '') + '>' +
'<div class="handle"></div>' +
'</div>' +
'</div></td>' +
'<td class="option-description">Enables hilighting based off the strength of player statistics</td>' +
'</tr>' +
'<tr><th>Polling Rate (ms)</th><td><input id="as-polling-rate" type="number" name="as-polling-rate" value="' + instance.storage('pollingIntervalMs').toString() + '"></td>' +
'<td class="option-description">The frequency the scoreboard queries the gameserver for information. 5000ms is the default</td>' +
'</tr>';
html += '</table>';
/** Input field for polling rate **/
/** Check box for hilighting **/
$('#as-scoreboard-container').html(html);
},
/**
* Draws settings HTML
*
*/
renderSettings : function(instance){
var html = '';
html += '<div id="advs_scoreboard_settings">';
html += '<h4 class="advs_title">' + instance.t("settings-title") + '</h4>';
/** Check box for live update **/
html += '<div class="as-settings-option"><label class="as-settings-label" for="as-enable-live">Live Scoreboard</label>';
html += '<input id="as-enable-live" type="checkbox" name="as-enable-live" value="'+ instance.storage('liveEnabled').toString() +'" '+ (instance.storage('liveEnabled') == true ? 'checked' : '') + '>';
html += '</div>';
/** Check box for hilighting **/
html += '<div class="as-settings-option"><label class="as-settings-label" for="as-enable-hilighting">Enable Hilighting</label>';
html += '<input id="as-enable-hilighting" type="checkbox" name="as-enable-hilighting" value="'+ instance.storage('hilightingEnabled').toString() +'" '+ (instance.storage('hilightingEnabled') == true ? 'checked' : '') + '>';
html += '</div>';
/** Check box for hilighting friends **/
html += '<div class="as-settings-option"><label class="as-settings-label" for="as-enable-friend-hilighting">Hilight Friends</label>';
html += '<input id="as-enable-friend-hilighting" type="checkbox" name="as-enable-friend-hilighting" value="'+ instance.storage('hilightFriends').toString() +'" '+ (instance.storage('hilightFriends') == true ? 'checked' : '') + '>';
html += '</div>';
/** **/
html += '<div class="as-about" style="font-size: 10px;"><p>Advanced Scoreboard 0.1.1 Beta</p><p>Developed by Cr1N</p></div>';
html += '</div>';
$("#content").append(html);
},
drawRoundInfo : function(instance)
{
var serverHeader = '<div id="as-scoreboard-roundinfo">';
serverHeader += '<div id="as-scoreboard-mapinfo"></div>';
serverHeader += '<div id="as-scoreboard-round-properties">' +
'<div><span>Players : </span><span id="as-server-players"></span></div>' +
'<div><span>Time : </span><span id="as-server-time-remaining"></span></div>' +
'</div>';
serverHeader += '<div id="as-scoreboard-options">' +
'<div class="as-sort-option"><label class="as-settings-label" for="as-select-display-stat">Show: </label><select id="as-select-display-stat">';
var existingDisplayStat = instance.storage('displayStat');
var customStats = ['skill', 'kdRatio', 'kills', 'deaths', 'strength'];
for(var i = 0; i < customStats.length; i++)
{
if(customStats[i] !== existingDisplayStat) {
serverHeader += '<option value="' + customStats[i] + '">' + instance.lookup.displayStat(customStats[i]) + '</option>';
} else {
serverHeader += '<option value="' + customStats[i] + '" selected>' + instance.lookup.displayStat(customStats[i]) + '</option>';
}
}
serverHeader += '</select></div></div>';
return serverHeader;
},
drawSelectors : function(instance) {
var selectors = [
{ htmlId: 'as-show-players', htmlText: 'Show Players', drawMode: 'player' },
{ htmlId: 'as-show-squads', htmlText: 'Show Squads', drawMode: 'squad' },
{ htmlId: 'as-show-roles', htmlText: 'Show Vehicles', drawMode: 'role' },
{ htmlId: 'as-show-charts', htmlText: 'Show Charts', drawMode: 'charts' },
];
selectorHtml = '<div id="as-scoreboard-selectors">';
for (var i = 0; i < selectors.length; i++) {
var selector = selectors[i];
selectorHtml += '<button class="btn view-selector ' + (instance.data.drawMode === selector.drawMode ? 'btn-primary' : '') + '" id="' + selector.htmlId + '">' + selector.htmlText + '</button>';
}
selectorHtml += '<button class="btn view-selector" id="as-settings">Settings</button>';
selectorHtml += '</div>';
return selectorHtml;
},
/**
* Simple debugging
*
* @param msg Debug message
*/
debug: function(msg) {
if(true)
console.log(msg);
},
/**
* Returns JSON object containing server attributes extracted from the DOM
*
* @return JSON object containing server data
*/
getServerAttributes : function() {
var $joinMpServerButton = $("#server-page-join-buttons");
var server = {
ip: $joinMpServerButton.data("ip"),
gameId: $joinMpServerButton.attr("data-gameid"),
port: $joinMpServerButton.data("port"),
game: $joinMpServerButton.data("game"),
guid: $joinMpServerButton.data("guid")
};
return server;
},
/**
* Returns scoreboard data from the game server
*
* @callback callback Callback function
* @param serverInfo Server information in JSON format
*
*/
queryServerScoreboard : function(serverInfo, callback) {
launcher.queryServer(serverInfo, function(queryInfo) {
if(!queryInfo) {
console.log("Could not obtain query info from the server!");
} else {
if(queryInfo.status == "OK") {
callback(queryInfo.result)
} else {
$("#as-scoreboard-container").html('<div class="as-scoreboard-roundfinished">Round is over. Waiting for next round to start...</div>');
console.log("Round has not started");
}
}
});
},
/**
* Checks for players who don't't have their statistics cached and fetches them
*
* @param scoreboardData Scoreboard data from the game server
* @param instance Plugin instance
*
*/
updatePlayerStats: function (instance, scoreboardData)
{
var updatePlayers = [];
var toLoad = 0;
var loaded = 0;
//For each team
$.each(scoreboardData.teams, function (teamID, team) {
$.each(team.players, function (playerId, player) {
if (!instance.playerStats.hasOwnProperty(player.personaId)) {
toLoad++;
}
});
});
$.each(scoreboardData.teams, function (teamID, team)
{
//For each player in the team
$.each(team.players, function (playerID, player)
{
//Only load the statistics if they are not already present in the database
if (!instance.playerStats.hasOwnProperty(player.personaId)) {
var playerName = player.tag ? '[' + player.tag + ']' + player.name : player.name;
instance.loadPlayerStats(player.personaId, playerName, function (overviewStats, playerName)
{
instance.playerStats[player.personaId] = overviewStats.data;
instance.playerStats[player.personaId]["name"] = playerName;
loaded++;
if (loaded == toLoad) {
instance.updateHTML(instance);
}
})
}
});
})
},
/**
* Return player status
*
* @callback callback Callback function
* @param personaId Persona ID of the player to be queried
*
*/
loadPlayerStats: function (personaId, playerName, callback)
{
$.ajax({
url: "http://battlelog.battlefield.com/bf4/warsawoverviewpopulate/" + personaId + "/1/",
type: 'GET',
async: true,
cache: false,
timeout: 30000,
success: function(data) {
callback(data, playerName);
}
});
},
/**
* Returns a players weapon stats
*
* @callback callback Callback function
* @param personaId Persona ID of the player to fetch
*/
loadPlayerWeaponStats: function (personaId, callback)
{
$.ajax({
url: "http://battlelog.battlefield.com/bf4/warsawWeaponsPopulateStats/" + personaId + "/1/stats/",
type: 'GET',
async: true,
cache: false,
timeout: 30000,
success: function(data) {
callback(data);
}
});
},
/**
* Returns a players vehicle stats stats
*
* @callback callback Callback function
* @param personaId Persona ID of the player to fetch
*/
loadPlayerVehicleStats : function(personaId, callback)
{
$.ajax({
url: "http://battlelog.battlefield.com/bf4/warsawvehiclesPopulateStats/" + personaId + "/1/stats/",
type: 'GET',
async: true,
cache: false,
timeout: 30000,
success: function (data) {
callback(data);
}
});
},
lookup : {
displayStat : function(displayStatValue){
var displayStatsLookup = {
'skill' : 'Skill',
'kdRatio' : 'K/D (G)',
'kills' : 'Kills',
'deaths': 'Deaths',
'strength' : 'Strength'
};
return displayStatsLookup[displayStatValue];
},
teamName : function(gameMode, status) {
if(gameMode == 2) return status.teamType.charAt(0).toUpperCase() + status.teamType.slice(1);
var factions = ["US", "RU", "CN"];
return factions[status.faction];
},
teamType : function(teamId) {
if(teamId == 1) {
var type = 'home'
} else {
var type = 'away';
}
return type;
},
teamFlag : function(teamName)
{
var urlPrefix = "http://eaassets-a.akamaihd.net/bl-cdn/cdnprefix/2e8fa20e7dba3f4aecb727fc8dcb902f1efef569b/public/common/flags/";
if (teamName == "US" || teamName == "RU" || teamName == "CN") {
return urlPrefix + teamName.toLowerCase() + '.gif';
} else {
return false
}
},
squadName : function(squadId) {
var squads = ["No Squad", "Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India", "Juliett", "Kilo", "Lima", "Mike"];
return squads[squadId];
},
gameMode: function (mode)
{
var gameModes = { 2: "Rush", 64: "Conquest Large" }
if( gameModes.hasOwnProperty(mode) ) {
return gameModes[mode];
} else {
return "Unknown Gamemode";
}
},
/*
* Match the players stat to a hilighting class based on a defined statistic
*
*/
hilightingClass: function (displayStat, pDisplayStat) {
if (displayStat == 'kdRatio') {
if (pDisplayStat < 1) {
hilightingType = 'low';
} else if (pDisplayStat < 2) {
hilightingType = 'average';
} else if (pDisplayStat < 3) {
hilightingType = 'good';
} else if (pDisplayStat < 4) {
hilightingType = 'high';
} else if (pDisplayStat < 5) {
hilightingType = 'v-high';
} else if (pDisplayStat >= 5) {
hilightingType = 'pro';
}
} else if (displayStat == 'skill') {
if (pDisplayStat < 200) {
hilightingType = 'low';
} else if (pDisplayStat < 300) {
hilightingType = 'average';
} else if (pDisplayStat < 400) {
hilightingType = 'good';
} else if (pDisplayStat < 550) {
hilightingType = 'high';
} else if (pDisplayStat >= 550) {
hilightingType = 'v-high';
}
}
else if (displayStat == 'strength') {
if (pDisplayStat < 200) {
hilightingType = 'low';
} else if (pDisplayStat < 300) {
hilightingType = 'average';
} else if (pDisplayStat < 400) {
hilightingType = 'good';
} else if (pDisplayStat < 550) {
hilightingType = 'high';
} else if (pDisplayStat >= 550) {
hilightingType = 'v-high';
}
}
return hilightingType;
}
},
sortBy : function(field, reverse, primer)
{
var key = function (x) {return primer ? primer(x[field]) : x[field]};
return function (a,b) {
var A = key(a), B = key(b);
return ( (A < B) ? -1 : ((A > B) ? 1 : 0) ) * [-1,1][+!!reverse];
}
},
commaFormat : function(number)
{
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
},
/**
*
* Unloads plugin by clearing variables and intervals
*
* @param instance Plugin Instance
*/
unloadPlugin : function(instance) {
//Clear interval
if(instance.data.asLiveUpdate) {
clearInterval(instance.data.asLiveUpdate);
}
//instance.data.latestScoreboardData = {};
instance.data.advancedViewPlayer = 0;
instance.data.asLiveUpdate = false;
instance.data.pluginLoaded = false;
instance.data.currentChart = false;
for(var tracked in instance.data.tracker)
{
instance.data.tracker[tracked] = {};
}
instance.debug("Plugin unloaded")
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment