2172 lines
63 KiB
JavaScript
Executable File
2172 lines
63 KiB
JavaScript
Executable File
|
|
var vBoxWidth = 1200,
|
|
vBoxHeight = 900,
|
|
bgWidth = 900,
|
|
bgHeight = 1500,
|
|
clicked;
|
|
|
|
//Object used for local storage of the user selections - had to use underscores instead of hyphen
|
|
var pageData = {
|
|
build: 0,
|
|
level: 0,
|
|
platform: 0,
|
|
overlay_group: 0,
|
|
overlay_single: 0,
|
|
deaths_game_type_select: 0,
|
|
data_resolution: 0,
|
|
fps_game_type: 0,
|
|
build_config: 0,
|
|
metric: 0,
|
|
draw_list: 0,
|
|
statistics: 0,
|
|
automated_tests_check: false,
|
|
automated_tests_select: 0,
|
|
fps_off_mission_cutscene: false,
|
|
cps_metric: 0,
|
|
cps_draw_list: 0,
|
|
cps_statistics: 0,
|
|
pst_statistics: 0,
|
|
msf_game_type: 0,
|
|
msf_memory_type: 0,
|
|
msf_statistics: 0,
|
|
}
|
|
|
|
var totalAjaxRequests = 7;
|
|
var completedAjaxRequests = 0;
|
|
|
|
var forceUrlSuffix = "";
|
|
var fpsTelemetryData,
|
|
pstTelemetryData,
|
|
msfTelemetryData;
|
|
|
|
var interpolationColours = ["#E51616", "#E2C016", "#59E016"]; // red - yellow - green
|
|
|
|
function convert2WebXCoord(x) {
|
|
return ((x + project.map.coords.x)/project.map.scale);
|
|
}
|
|
function convert2WebYCoord(y) {
|
|
return (((-1)*y + project.map.coords.y)/project.map.scale);
|
|
}
|
|
function convert2WebCoords(p) {
|
|
return [convert2WebXCoord(p[0]), convert2WebYCoord(p[1])];
|
|
}
|
|
|
|
function convertFromWebXCoord(x) {
|
|
return (-1) * ((project.map.coords.x) - (x*project.map.scale));
|
|
}
|
|
function convertFromWebYCoord(y) {
|
|
return ((project.map.coords.y) - (y*project.map.scale));
|
|
}
|
|
|
|
function updateMapHeight() {
|
|
// Adjust the height of the map automatically
|
|
var windowHeight = $(window).height() - 3.0 * $("#sub-header").height();
|
|
//console.log(windowHeight);
|
|
$("#map-wrapper").css("height", windowHeight);
|
|
}
|
|
|
|
function initPage() {
|
|
// function from generic.js, variable from config file
|
|
//initHeaderAndFilters(headerAndFilters);
|
|
initHeaderAndFilters(null);
|
|
updateMapHeight();
|
|
|
|
var localData = retrieveLocalObject(config.currentFilename);
|
|
pageData = (localData) ? localData : pageData;
|
|
|
|
block();
|
|
$.ajax({
|
|
url: project.map.svgFile,
|
|
type: "GET",
|
|
data: {},
|
|
dataType: "xml",
|
|
|
|
success: function(xml, textStatus, jqXHR) {
|
|
var importedNode;
|
|
try {
|
|
importedNode = document.importNode(xml.documentElement, true);
|
|
}
|
|
catch(e) {
|
|
// IE case
|
|
importedNode = ieImportNode(xml.documentElement, document);
|
|
}
|
|
|
|
$("#map").append(importedNode);
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError){
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError );
|
|
},
|
|
complete: function() {
|
|
++completedAjaxRequests;
|
|
|
|
var svg = d3.select("#map svg")
|
|
.attr("width", $("#map").width())
|
|
.attr("height", $("#map").height())
|
|
.attr("enable-background", "new 0 0 " + bgWidth + " "+ bgHeight)
|
|
.call(svg_interact);
|
|
|
|
drawGrid();
|
|
}
|
|
});
|
|
|
|
$.ajax({
|
|
url: config.restHost + config.buildsAll,
|
|
type: "GET",
|
|
data: {},
|
|
dataType: "json",
|
|
|
|
success: function(json, textStatus, jqXHR) {
|
|
var builds = json.Items.sort(function(a, b) { return((a.Identifier > b.Identifier) ? -1 : 1); });
|
|
|
|
$.each(builds, function(i, build) {
|
|
if (!build.GameVersion)
|
|
return;
|
|
|
|
var titleExtra = [];
|
|
$("select#build").append(
|
|
$("<option />")
|
|
.html(function() {
|
|
var hasExtra = [];
|
|
var text = build.Identifier;
|
|
|
|
if (build.HasAutomatedEverythingStats) {
|
|
hasExtra.push("AE");
|
|
titleExtra.push("Automated Everything");
|
|
}
|
|
if (build.HasAutomatedMapOnlyStats) {
|
|
hasExtra.push("MO");
|
|
titleExtra.push("Automated Map Only");
|
|
}
|
|
if (build.HasMemShortfallStats) {
|
|
hasExtra.push("MS");
|
|
titleExtra.push("Memory Shortfall");
|
|
}
|
|
if (build.HasShapeTestStats) {
|
|
hasExtra.push("ST");
|
|
titleExtra.push("Shape Test");
|
|
}
|
|
|
|
return (hasExtra.length > 0) ? (text + " (" + hasExtra.join(",") + ")" ): text;
|
|
})
|
|
.attr("title", function() {
|
|
var title = build.Identifier;
|
|
return (titleExtra.length > 0) ? (title + " (" + titleExtra.join(", ") + ")" ): title;
|
|
})
|
|
.val(build.Identifier)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.build == build.Identifier) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError);
|
|
},
|
|
complete: function() {
|
|
++completedAjaxRequests;
|
|
}
|
|
|
|
});
|
|
|
|
$.ajax({
|
|
url: config.restHost + config.levelsAll,
|
|
type: "GET",
|
|
data: {},
|
|
dataType: "xml",
|
|
|
|
success: function(xml, textStatus, jqXHR) {
|
|
var levels = convertLevelsXml(xml);
|
|
|
|
$.each(levels, function(i, level) {
|
|
$("select#level").append(
|
|
$('<option />')
|
|
.text(level.Name)
|
|
.val(level.Identifier)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.level == level.Identifier) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError);
|
|
},
|
|
complete: function() {
|
|
++completedAjaxRequests;
|
|
}
|
|
});
|
|
|
|
|
|
// Platforms List
|
|
/*
|
|
$.ajax({
|
|
url: config.restHost + config.platformsAll,
|
|
type: "GET",
|
|
data: {},
|
|
dataType: "xml",
|
|
|
|
success: function(xml, textStatus, jqXHR) {
|
|
var platforms = convertPlatformsXml(xml);
|
|
|
|
$.each(platforms, function(i, platform) {
|
|
$("select#platform").append(
|
|
$('<option />')
|
|
.text(platform.Value)
|
|
.val(platform.Value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.platform == platform.Value) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError);
|
|
},
|
|
complete: function() {
|
|
++completedAjaxRequests;
|
|
}
|
|
});
|
|
*/
|
|
var platforms = getPlatforms();
|
|
$.each(platforms, function(i, platform) {
|
|
$("select#platform").append(
|
|
$('<option />')
|
|
.text(platform.Name)
|
|
.val(platform.Name)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.platform == platform.Name) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
++completedAjaxRequests;
|
|
|
|
// Overlay Groups
|
|
$.each(config.overlayGroupsAll, function(i, overlayGroup) {
|
|
$("select#overlay-group").append(
|
|
$('<option />')
|
|
.text(overlayGroup)
|
|
.val(overlayGroup)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.overlay_group == overlayGroup) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
// Overlays
|
|
$.each(config.overlaysAll, function(i, overlaySingle) {
|
|
$("select#overlay-single").append(
|
|
$('<option />')
|
|
.text(overlaySingle.Name)
|
|
.val(overlaySingle.Value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.overlay_single == overlaySingle.Value) ? "selected" : false;
|
|
})
|
|
);
|
|
})
|
|
|
|
// Resolutions List
|
|
$.each(config.resolutionsAll, function(i, value) {
|
|
$("select#data-resolution").append(
|
|
$('<option />')
|
|
.text(value)
|
|
.val(value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.data_resolution == value) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
/*
|
|
// Resolutions List
|
|
$.ajax({
|
|
url: config.restHost + config.resolutionsAll,
|
|
type: "GET",
|
|
data: {},
|
|
dataType: "xml",
|
|
|
|
success: function(xml, textStatus, jqXHR) {
|
|
var resolutions = convertResolutionsXml(xml);
|
|
|
|
$.each(resolutions, function(i, resolution) {
|
|
$("select#data-resolution").append(
|
|
$("<option />")
|
|
.text(resolution.BlockSize)
|
|
.val(resolution.Id)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.data_resolution == resolution.Id) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError);
|
|
},
|
|
complete: function() {
|
|
++completedAjaxRequests;
|
|
}
|
|
|
|
});
|
|
*/
|
|
|
|
// Gametypes List
|
|
/*
|
|
$.ajax({
|
|
url: config.restHost + config.gametypesAll,
|
|
type: "GET",
|
|
data: {},
|
|
dataType: "xml",
|
|
|
|
success: function(xml, textStatus, jqXHR) {
|
|
var gametypes = convertGametypesXml(xml);
|
|
|
|
$.each(gametypes, function(i, gametype) {
|
|
$("select#fps-game-type").append(
|
|
$('<option />')
|
|
.text(gametype.Value)
|
|
.val(gametype.Value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.fps_game_type == gametype.Value) ? "selected" : false;
|
|
})
|
|
);
|
|
$("select#deaths-game-type-select").append(
|
|
$('<option />')
|
|
.text(gametype.Value)
|
|
.val(gametype.Value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.deaths_game_type_select == gametype.Value)
|
|
? "selected" : false;
|
|
})
|
|
);
|
|
$("select#msf-game-type").append(
|
|
$('<option />')
|
|
.text(gametype.Value)
|
|
.val(gametype.Value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.msf_game_type == gametype.Value)
|
|
? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError);
|
|
},
|
|
complete: function() {
|
|
++completedAjaxRequests;
|
|
}
|
|
|
|
});
|
|
*/
|
|
var gameTypes = getGameTypes();
|
|
$.each(gameTypes, function(i, gametype) {
|
|
$("select#fps-game-type").append(
|
|
$('<option />')
|
|
.text(gametype.Name)
|
|
.val(gametype.Name)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.fps_game_type == gametype.Name) ? "selected" : false;
|
|
})
|
|
);
|
|
$("select#deaths-game-type-select").append(
|
|
$('<option />')
|
|
.text(gametype.Name)
|
|
.val(gametype.Name)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.deaths_game_type_select == gametype.Name)
|
|
? "selected" : false;
|
|
})
|
|
);
|
|
$("select#msf-game-type").append(
|
|
$('<option />')
|
|
.text(gametype.Name)
|
|
.val(gametype.Name)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.msf_game_type == gametype.Name)
|
|
? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
++completedAjaxRequests;
|
|
|
|
// BuildConfigs List
|
|
/*
|
|
$.ajax({
|
|
url: config.restHost + config.buildConfigsAll,
|
|
type: "GET",
|
|
data: {},
|
|
dataType: "xml",
|
|
|
|
success: function(xml, textStatus, jqXHR) {
|
|
|
|
var buildConfigs = convertBuildConfigsXml(xml);
|
|
|
|
$.each(buildConfigs, function(i, buildConfig) {
|
|
$("select#build-config").append(
|
|
$('<option />')
|
|
.text(buildConfig.Value)
|
|
.val(buildConfig.Value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.build_config == buildConfig.Value) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError);
|
|
},
|
|
complete: function() {
|
|
++completedAjaxRequests;
|
|
}
|
|
|
|
});
|
|
*/
|
|
var buildConfigs = getBuildConfigs();
|
|
$.each(buildConfigs, function(i, buildConfig) {
|
|
$("select#build-config").append(
|
|
$('<option />')
|
|
.text(buildConfig.Name)
|
|
.val(buildConfig.Name)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.build_config == buildConfig.Name) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
++completedAjaxRequests;
|
|
|
|
// Metric List
|
|
$.each(config.metricAll, function(i, metric) {
|
|
$("select#metric").append(
|
|
$('<option />')
|
|
.text(metric)
|
|
.val(metric)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.metric == metric) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
// Draw List
|
|
$.ajax({
|
|
url: config.restHost + config.drawListAll,
|
|
type: "GET",
|
|
data: {},
|
|
dataType: "json",
|
|
|
|
success: function(json, textStatus, jqXHR) {
|
|
var drawList = json.sort(function(a, b) {return (a.GameName < b.GameName) ? -1 : 1});
|
|
//var drawList = convertDrawListXml(xml);
|
|
|
|
$.each(drawList, function(i, draw) {
|
|
$("select#draw-list").append(
|
|
$('<option />')
|
|
.text(draw.GameName)
|
|
.val(draw.GameName)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.draw_list == draw.GameName) ? "selected" : false;
|
|
})
|
|
);
|
|
$("select#cps-draw-list").append(
|
|
$('<option />')
|
|
.text(draw.GameName)
|
|
.val(draw.GameName)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.cps_draw_list == draw.GameName) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError);
|
|
},
|
|
complete: function() {
|
|
++completedAjaxRequests;
|
|
}
|
|
});
|
|
|
|
/*
|
|
// Social Club Freemode Matches
|
|
$.ajax({
|
|
url: config.restHost + config.SCFreemodeNames,
|
|
type: "GET",
|
|
data: {type: "DEATHMATCH"},
|
|
dataType: "json",
|
|
|
|
success: function(deathmatches, textStatus, jqXHR) {
|
|
$.each(deathmatches, function(i, deathmatch) {
|
|
$("select#deathmatch-list").append(
|
|
$('<option />')
|
|
.text(deathmatch.Name + " (" + deathmatch.Creator + ")")
|
|
.val(deathmatch.UGCIdentifier)
|
|
.attr("title", deathmatch.Name + " (" + deathmatch.Creator + ") : " + deathmatch.Description)
|
|
)
|
|
});
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError);
|
|
},
|
|
complete: function() {
|
|
++completedAjaxRequests;
|
|
}
|
|
});
|
|
*/
|
|
|
|
// Statistics List
|
|
$.each(config.statAll, function(i, stat) {
|
|
$("select#statistics").append(
|
|
$("<option />")
|
|
.text(stat.Name)
|
|
.val(stat.Value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.statistics == stat.Value) ? "selected" : false;
|
|
})
|
|
);
|
|
$("select#cps-statistics").append(
|
|
$("<option />")
|
|
.text(stat.Name)
|
|
.val(stat.Value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.cps_statistics == stat.Value) ? "selected" : false;
|
|
})
|
|
);
|
|
$("select#pst-statistics").append(
|
|
$("<option />")
|
|
.text(stat.Name)
|
|
.val(stat.Value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.pst_statistics == stat.Value) ? "selected" : false;
|
|
})
|
|
);
|
|
$("select#msf-statistics").append(
|
|
$("<option />")
|
|
.text(stat.Name)
|
|
.val(stat.Value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.msf_statistics == stat.Value) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
// Automated Tests check
|
|
if (pageData && pageData.automated_tests_check) {
|
|
$("#automated-tests input[type=checkbox]").prop("checked", true);
|
|
$("#automated-tests-select").attr("disabled", false);
|
|
}
|
|
else {
|
|
$("#automated-tests input[type=checkbox]").prop("checked", false);
|
|
$("#automated-tests-select").attr("disabled", true);
|
|
}
|
|
|
|
// Automated Tests select
|
|
$.each(config.automatedTestsAll, function(i, automatedTest) {
|
|
$("select#automated-tests-select").append(
|
|
$('<option />')
|
|
.text(automatedTest.Name)
|
|
.val(automatedTest.Value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.automated_tests_select == automatedTest.Value) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
// For fps off missions/cutscene
|
|
if (pageData && pageData.fps_off_mission_cutscene) {
|
|
$("#fps-off-mission-cutscene").prop("checked", true);
|
|
}
|
|
else {
|
|
$("#fps-off-mission-cutscene").prop("checked", false);
|
|
}
|
|
|
|
// Memory Types select (for Memory Shortfall)
|
|
$.each(config.memoryTypesAll, function(i, memoryType) {
|
|
$("select#msf-memory-type").append(
|
|
$("<option />")
|
|
.text(memoryType.Name)
|
|
.val(memoryType.Value)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.msf_memory_type == memoryType.Value) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
|
|
toggleOverlayOptions($("select#overlay-single").val());
|
|
|
|
// Bind the events
|
|
$("#sub-header select").change(function() {
|
|
// If the select id is not the group overlay, then store the header options locally
|
|
if ($(this).attr("id") != "overlay-group") {
|
|
pageData[$(this).attr("id").replace(/\-/g, '_')] = $(this).val();
|
|
storeLocalObject(config.currentFilename, pageData);
|
|
}
|
|
|
|
if (($(this).attr("id") == "build") || ($(this).attr("id") == "level") || ($(this).attr("id") == "platform"))
|
|
//&& ($("select#overlay-single").val() == $("select#overlay-single option:eq(2)").val()))
|
|
updatePerformanceMetrics();
|
|
|
|
generateCustomOverlay();
|
|
});
|
|
$("#sub-header #filter-force").change(function() {
|
|
generateCustomOverlay();
|
|
});
|
|
|
|
|
|
$("select#overlay-single").change(function() {
|
|
toggleOverlayOptions($(this).val());
|
|
});
|
|
|
|
$(".overlay-options select").change(function() {
|
|
if ($(this).attr("id") != "deaths-list-select") {
|
|
pageData[$(this).attr("id").replace(/\-/g, '_')] = $(this).val();
|
|
storeLocalObject(config.currentFilename, pageData);
|
|
generateCustomOverlay();
|
|
}
|
|
});
|
|
|
|
/*
|
|
$("#fps-overlay-options select").change(function() {
|
|
pageData[$(this).attr("id").replace(/\-/g, '_')] = $(this).val();
|
|
storeLocalObject(config.currentFilename, pageData);
|
|
|
|
generateCustomOverlay();
|
|
});
|
|
*/
|
|
|
|
$("#fps-overlay-options select#metric").change(function() {
|
|
if ($(this).val() == config.fpsDrawListMetricName)
|
|
$("#fps-overlay-options select#draw-list").attr("disabled", false);
|
|
else
|
|
$("#fps-overlay-options select#draw-list").attr("disabled", true);
|
|
});
|
|
|
|
$("#fps-off-mission-cutscene").click(function() {
|
|
pageData[$(this).attr("id").replace(/\-/g, '_')] = $(this).is(":checked");
|
|
storeLocalObject(config.currentFilename, pageData);
|
|
|
|
generateCustomOverlay();
|
|
});
|
|
|
|
$("#automated-tests input[type=checkbox]").click(function() {
|
|
if ($(this).is(":checked")) {
|
|
$("#automated-tests-select").attr("disabled", false);
|
|
pageData[$(this).attr("id").replace(/\-/g, '_')] = true;
|
|
}
|
|
else {
|
|
$("#automated-tests-select").attr("disabled", true);
|
|
pageData[$(this).attr("id").replace(/\-/g, '_')] = false;
|
|
}
|
|
storeLocalObject(config.currentFilename, pageData);
|
|
generateCustomOverlay();
|
|
});
|
|
|
|
/*
|
|
$("#deaths-game-type select").change(function() {
|
|
pageData[$(this).attr("id").replace(/\-/g, '_')] = $(this).val();
|
|
storeLocalObject(config.currentFilename, pageData);
|
|
|
|
generateCustomOverlay();
|
|
});
|
|
*/
|
|
|
|
$("#deaths-list select").change(function() {
|
|
highlightCircle($(this).val());
|
|
});
|
|
|
|
$("input#time-since-spawn").change(function() {
|
|
generateCustomOverlay();
|
|
});
|
|
|
|
/*
|
|
$("select#deathmatch-list").change(function() {
|
|
generateCustomOverlay();
|
|
});
|
|
*/
|
|
|
|
/*
|
|
$("#cps-overlay-options select").change(function() {
|
|
pageData[$(this).attr("id").replace(/\-/g, '_')] = $(this).val();
|
|
storeLocalObject(config.currentFilename, pageData);
|
|
|
|
generateCustomOverlay();
|
|
});
|
|
*/
|
|
|
|
$("#cps-overlay-options select#cps-metric").change(function() {
|
|
if ($(this).val() == config.cpsDrawListMetricName)
|
|
$("#cps-overlay-options select#cps-draw-list").attr("disabled", false);
|
|
else
|
|
$("#cps-overlay-options select#cps-draw-list").attr("disabled", true);
|
|
});
|
|
|
|
/*
|
|
$("#pst-overlay-options select").change(function() {
|
|
pageData[$(this).attr("id").replace(/\-/g, '_')] = $(this).val();
|
|
storeLocalObject(config.currentFilename, pageData);
|
|
|
|
generateCustomOverlay();
|
|
});
|
|
|
|
$("#msf-overlay-options select").change(function() {
|
|
pageData[$(this).attr("id").replace(/\-/g, '_')] = $(this).val();
|
|
storeLocalObject(config.currentFilename, pageData);
|
|
|
|
generateCustomOverlay();
|
|
});
|
|
*/
|
|
|
|
//$("#map-layers :checkbox").click(function(){
|
|
// The following declaration is faster than the latter
|
|
$("#map-layers input[type=checkbox]").click(function() {
|
|
var layer = d3.select("#map svg").select("g#" + $(this).val());
|
|
|
|
if ($(this).is(":checked")) {
|
|
layer
|
|
.transition()
|
|
.attr("opacity", 1);
|
|
}
|
|
else {
|
|
layer
|
|
.transition()
|
|
.attr("opacity", 0.01);
|
|
}
|
|
});
|
|
|
|
// Initialise the overlay
|
|
$("#performance-overlay").overlay({
|
|
mask: {
|
|
color: "#222",
|
|
loadSpeed: "fast",
|
|
opacity: 0.5,
|
|
},
|
|
top: "10%",
|
|
closeOnClick: false,
|
|
load: false,
|
|
});
|
|
|
|
$(window).resize(updateMapHeight);
|
|
|
|
$("#filter").click(function() {
|
|
generateCustomOverlay();
|
|
});
|
|
|
|
completePage();
|
|
}
|
|
|
|
function completePage() {
|
|
//console.log(completedAjaxRequests);
|
|
if (completedAjaxRequests < totalAjaxRequests) {
|
|
setTimeout(completePage, 500)
|
|
}
|
|
else {
|
|
unBlock();
|
|
|
|
updatePerformanceMetrics();
|
|
// Generate overlay if an overlay group is selected by default
|
|
generateCustomOverlay();
|
|
}
|
|
}
|
|
|
|
function updatePerformanceMetrics() {
|
|
block();
|
|
$.ajax({
|
|
url: config.restHost + config.capturePerformanceMetrics,
|
|
type: "GET",
|
|
dataType: "json",
|
|
data: {
|
|
build: $("select#build").val(),
|
|
level: $("select#level").val(),
|
|
platform: $("select#platform").val(),
|
|
},
|
|
async: false,
|
|
|
|
success: function(json, textStatus, jqXHR) {
|
|
$("select#cps-metric").empty();
|
|
$.each(json, function(i, metric) {
|
|
$("select#cps-metric").append(
|
|
$('<option />')
|
|
.text(metric)
|
|
.val(metric)
|
|
.attr("selected", function() {
|
|
return (pageData && pageData.cps_metric == metric) ? "selected" : false;
|
|
})
|
|
);
|
|
});
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError);
|
|
},
|
|
complete: function() {
|
|
unBlock();
|
|
}
|
|
});
|
|
}
|
|
|
|
function drawGrid() {
|
|
var gridStep = 500/project.map.scale; // The step of the grid in map coordinates
|
|
|
|
var grid = d3.select("#map svg")
|
|
.append("svg:g")
|
|
.attr("id", "grid");
|
|
|
|
var xAxisDataNeg = d3.range(convert2WebXCoord(0), 0, -gridStep);
|
|
var xAxisDataPos = d3.range(convert2WebXCoord(0), bgWidth, gridStep);
|
|
|
|
var yAxisDataNeg = d3.range(convert2WebYCoord(0), 0, -gridStep);
|
|
var yAxisDataPos = d3.range(convert2WebYCoord(0), bgHeight, gridStep);
|
|
|
|
grid.selectAll("line.vertical")
|
|
.data(xAxisDataNeg.concat(xAxisDataPos))
|
|
.enter()
|
|
.append("svg:line")
|
|
.attr("x1", function(d) {return d;})
|
|
.attr("y1", 0)
|
|
.attr("x2", function(d) {return d;})
|
|
.attr("y2", bgHeight)
|
|
.attr("class", "map-grid");
|
|
|
|
grid.selectAll("line.horizontal")
|
|
.data(yAxisDataNeg.concat(yAxisDataPos))
|
|
.enter()
|
|
.append("svg:line")
|
|
.attr("x1", 0)
|
|
.attr("y1", function(d) {return d;})
|
|
.attr("x2", bgWidth)
|
|
.attr("y2", function(d) {return d;})
|
|
.attr("class", "map-grid");
|
|
}
|
|
|
|
function drawFpsHeatmap(cached) {
|
|
var resolution = Number($("select#data-resolution").val()),
|
|
metric = $("select#metric").val(),
|
|
stat = capitaliseString($("select#statistics").val());
|
|
|
|
if (!cached) {
|
|
var pValues = {
|
|
//ForceUrlSuffix: forceUrlSuffix,
|
|
ElementKeyName: "Name",
|
|
ElementValueName: "Value",
|
|
Pairs: {
|
|
"BuildIdentifier": $("select#build").val(),
|
|
"LevelIdentifier": $("select#level").val(),
|
|
"PlatformName": $("select#platform").val(),
|
|
"Resolution" : resolution,
|
|
"BuildConfigName" : $("select#build-config").val(),
|
|
"GameTypeName" : $("select#fps-game-type").val(),
|
|
"DrawListName" : $("select#draw-list").val(),
|
|
"OffMissionAndCutsceneOnly" : $("#fps-off-mission-cutscene").is(":checked"),
|
|
},
|
|
};
|
|
|
|
if ($("#automated-tests input[type=checkbox]").is(":checked")) {
|
|
var autoTestNum = parseInt($("#automated-tests-select").val());
|
|
//console.log(autoTestNum);
|
|
pValues.Pairs["AutomatedTestNumber"] = autoTestNum;
|
|
}
|
|
|
|
var restEndpoint, restEndpointAsync;
|
|
if ($("#fps-overlay-options select#metric :selected").val() == config.fpsDrawListMetricName) { // == DrawLists
|
|
restEndpoint = config.fpsDrawListPerformanceStats,
|
|
restEndpointAsync = config.fpsDrawListPerformanceStatsAsync + forceUrlSuffix;
|
|
}
|
|
else {
|
|
restEndpoint = config.fpsPerformanceStats,
|
|
restEndpointAsync = config.fpsPerformanceStatsAsync + forceUrlSuffix;
|
|
}
|
|
|
|
var req = new ReportRequest(config.restHost + restEndpoint,
|
|
"json",
|
|
config.restHost + restEndpointAsync,
|
|
config.restHost + config.reportsQueryAsync);
|
|
req.sendSingleAsyncRequest(pValues, handleFpsPerformanceResults);
|
|
}
|
|
else {
|
|
handleFpsPerformanceResults(fpsTelemetryData);
|
|
}
|
|
|
|
function handleFpsPerformanceResults(telemetryData) {
|
|
// Save for later
|
|
fpsTelemetryData = telemetryData
|
|
|
|
var valueFunc = function(d) {
|
|
return ((metric != config.fpsDrawListMetricName) ? d[stat + metric] : d[stat + "EntityCount"]);
|
|
}
|
|
|
|
generateGenericHeatmap(telemetryData, resolution, valueFunc, "fps-overlay-options");
|
|
}
|
|
|
|
} // end of drawFpsHeatmap()
|
|
|
|
function drawShapeTestHeatmap(cached) {
|
|
var resolution = 100;
|
|
|
|
if (!cached) {
|
|
var pValues = {
|
|
//ForceUrlSuffix: forceUrlSuffix,
|
|
ElementKeyName: "Name",
|
|
ElementValueName: "Value",
|
|
Pairs: {
|
|
"BuildIdentifier": $("select#build").val(),
|
|
"PlatformName": $("select#platform").val(),
|
|
"LevelIdentifier": $("select#level").val(),
|
|
"Resolution" : resolution,
|
|
}
|
|
};
|
|
|
|
var req = new ReportRequest(config.restHost + config.physicsShapeTestStats,
|
|
"json",
|
|
config.restHost + config.physicsShapeTestStatsAsync + forceUrlSuffix,
|
|
config.restHost + config.reportsQueryAsync);
|
|
req.sendSingleAsyncRequest(pValues, handlePhysicsShapeTestResults);
|
|
}
|
|
else {
|
|
handlePhysicsShapeTestResults(pstTelemetryData);
|
|
}
|
|
|
|
function handlePhysicsShapeTestResults(telemetryData) {
|
|
// Save for later
|
|
pstTelemetryData = telemetryData
|
|
|
|
var valueFunc = function(d) {
|
|
return d[capitaliseString($("select#pst-statistics").val())];
|
|
}
|
|
|
|
generateGenericHeatmap(telemetryData, resolution, valueFunc, "pst-overlay-options");
|
|
}
|
|
|
|
} // end of drawShapeTestHeatmap()
|
|
|
|
function drawShortfallHeatmap(cached) {
|
|
var resolution = 100;
|
|
var memoryType = $("select#msf-memory-type").val();
|
|
var stat = capitaliseString($("select#msf-statistics").val());
|
|
|
|
if (!cached) {
|
|
|
|
var pValues = {
|
|
//ForceUrlSuffix: forceUrlSuffix,
|
|
ElementKeyName: "Name",
|
|
ElementValueName: "Value",
|
|
Pairs: {
|
|
"BuildIdentifier": $("select#build").val(),
|
|
"PlatformName": $("select#platform").val(),
|
|
"LevelIdentifier": $("select#level").val(),
|
|
"Resolution" : resolution,
|
|
}
|
|
};
|
|
|
|
var req = new ReportRequest(config.restHost + config.memoryShortfallStats,
|
|
"json",
|
|
config.restHost + config.memoryShortfallStatsAsync + forceUrlSuffix,
|
|
config.restHost + config.reportsQueryAsync);
|
|
req.sendSingleAsyncRequest(pValues, handleShortfallResults);
|
|
}
|
|
else {
|
|
handleShortfallResults(msfTelemetryData);
|
|
}
|
|
|
|
function handleShortfallResults(telemetryData) {
|
|
// Save for later
|
|
msfTelemetryData = telemetryData
|
|
//console.log(telemetryData);
|
|
|
|
var valueFunc = function(d) {
|
|
//console.log(d[stat + memoryType]);
|
|
return d[stat + memoryType];
|
|
};
|
|
|
|
generateGenericHeatmap(telemetryData, resolution, valueFunc, "msf-overlay-options");
|
|
}
|
|
|
|
} // end of drawShortfallHeatmap()
|
|
|
|
|
|
function generateGenericHeatmap(telemetryData, resolution, valueFunc, domElement) {
|
|
showMsgWhenNoData(telemetryData);
|
|
|
|
var min = 0, max = 0;
|
|
$.each(telemetryData, function(i ,d) {
|
|
min = ((valueFunc(d) < min) ? valueFunc(d) : min);
|
|
max = ((valueFunc(d) > max) ? valueFunc(d) : max);
|
|
});
|
|
var med = ((min+max)/2);
|
|
|
|
var thresholdSlider = $("#" + domElement + " div.threshold-slider");
|
|
thresholdSlider.slider("option", "min", min);
|
|
thresholdSlider.slider("option", "max", max);
|
|
thresholdSlider.slider("refresh");
|
|
|
|
var valuesSlider = $("#" + domElement + " div.value-slider");
|
|
valuesSlider.slider("option", "min", min);
|
|
valuesSlider.slider("option", "max", max);
|
|
$("#" + domElement + " span.value-min").text(min.toFixed(2));
|
|
$("#" + domElement + " span.value-max").text(max.toFixed(2));
|
|
|
|
if ((valuesSlider.slider("values")[0] == min) && (valuesSlider.slider("values")[1] == min)) {
|
|
valuesSlider.slider("values", 0, min);
|
|
valuesSlider.slider("values", 1, max);
|
|
}
|
|
valuesSlider.slider("refresh");
|
|
|
|
rangeSliderValues = valuesSlider.slider("values");
|
|
var heatmapSliderValues = $("#" + domElement + " div.heatmap-slider-placeholder").slider("values");
|
|
var colourInterpolator = getColourInterpolator(rangeSliderValues[0], rangeSliderValues[1],
|
|
heatmapSliderValues[1], heatmapSliderValues[0]);
|
|
|
|
$("#" + domElement + " span.heatmap-gradient" + " span.heatmap-min").text(rangeSliderValues[0].toFixed(2));
|
|
$("#" + domElement + " span.heatmap-gradient" + " span.heatmap-med").text(
|
|
((rangeSliderValues[0] + rangeSliderValues[1]) / 2).toFixed(2)
|
|
);
|
|
$("#" + domElement + " span.heatmap-gradient" + " span.heatmap-max").text(rangeSliderValues[1].toFixed(2));
|
|
|
|
|
|
var heatmap = d3.select("#map svg").append("svg:g")
|
|
.attr("id", "telemetry-overlay")
|
|
.attr("opacity", 0.01);
|
|
|
|
heatmap
|
|
.selectAll("rect")
|
|
.data(telemetryData)
|
|
.enter()
|
|
.append("svg:rect")
|
|
.attr("x", function(d) {
|
|
return convert2WebXCoord(d.Location.X);
|
|
})
|
|
.attr("y", function(d) {
|
|
return convert2WebYCoord(d.Location.Y + resolution);
|
|
})
|
|
.attr("width", resolution/project.map.scale)
|
|
.attr("height", resolution/project.map.scale)
|
|
.attr("fill", function(d) {
|
|
return colourInterpolator(valueFunc(d));
|
|
})
|
|
.attr("visibility", function(d) { // Hide if below the threshold limit
|
|
return (valueFunc(d) >= thresholdSlider.slider("value")) ? "visible" : "hidden";
|
|
})
|
|
.on("click", click)
|
|
.append("title")
|
|
.text(function(d) {
|
|
var title = "Centre (x=" + (d.Location.X + resolution/2)
|
|
+ ", y=" + (d.Location.Y + resolution/2) + ")"
|
|
+ "\nValue : " + valueFunc(d).toFixed(2);
|
|
//console.log(d.SampleSize);
|
|
if ((typeof d.SampleSize) !== "undefined")
|
|
title += "\nSample Size : " + d.SampleSize;
|
|
|
|
return (title);
|
|
});
|
|
|
|
heatmap
|
|
.transition()
|
|
.attr("opacity", 1);
|
|
|
|
function click(d) {
|
|
|
|
if (d && clicked !== d) {
|
|
clicked = d;
|
|
}
|
|
else {
|
|
clicked = null;
|
|
}
|
|
|
|
heatmap.selectAll("rect")
|
|
.classed("active", clicked && function(d) { return d === clicked; });
|
|
}
|
|
|
|
}
|
|
// end of generateGenericHeatmap
|
|
|
|
function drawCpsHeatmap() {
|
|
var cpsMetric = $("select#cps-metric").val();
|
|
if (!cpsMetric)
|
|
return;
|
|
|
|
var restOptions = {
|
|
build: $("select#build").val(),
|
|
level: $("select#level").val(),
|
|
platform: $("select#platform").val(),
|
|
//resolution: 2,
|
|
metric: cpsMetric,
|
|
statistic: $("select#cps-statistics :selected").text(),
|
|
}
|
|
|
|
if (cpsMetric == config.cpsDrawListMetricName)
|
|
restOptions["drawList"] = $("select#cps-draw-list").val();
|
|
|
|
block();
|
|
|
|
$.ajax({
|
|
url: config.restHost + config.capturePerformanceStats,
|
|
type: "GET",
|
|
data: restOptions,
|
|
dataType: "json",
|
|
success: function(json, textStatus, jqXHR) {
|
|
//console.log(json)
|
|
|
|
var colour = d3.scale.linear()
|
|
.domain([33, 50, 66])
|
|
.range(interpolationColours);
|
|
|
|
//var resolution = parseInt($("select#data-resolution :selected").text());
|
|
var resolution = 100;
|
|
|
|
var heatmap = d3.select("#map svg").append("svg:g")
|
|
.attr("id", "telemetry-overlay")
|
|
.attr("opacity", 0.01);
|
|
|
|
showMsgWhenNoData(json.Items);
|
|
|
|
heatmap
|
|
.selectAll("rect")
|
|
.data(json.Items)
|
|
.enter()
|
|
.append("svg:rect")
|
|
.attr("x", function(d) {
|
|
return convert2WebXCoord(Number(d.Location.X));
|
|
})
|
|
.attr("y", function(d) {
|
|
return convert2WebYCoord(Number(d.Location.Y) + resolution);
|
|
})
|
|
.attr("width", resolution/project.map.scale)
|
|
.attr("height", resolution/project.map.scale)
|
|
.attr("fill", function(d) {
|
|
return colour(d.Value);
|
|
})
|
|
.on("mouseover", function() {
|
|
d3.select(this).classed("active", true);
|
|
})
|
|
.on("mouseout", function() {
|
|
d3.select(this).classed("active", false);
|
|
})
|
|
.on("click", showPerformanceDetails)
|
|
//.on("dblclick", showPerformanceDetails)
|
|
.append("title")
|
|
.text(function(d) {
|
|
var title = "Centre (x=" + (d.Location.X + resolution/2)
|
|
+ ", y=" + (d.Location.Y + resolution/2) + ")"
|
|
+ "\nValue : " + d.Value.toFixed(2)
|
|
+ "\nClick for Full Report";
|
|
return (title);
|
|
});
|
|
heatmap
|
|
.transition()
|
|
.attr("opacity", 1);
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError );
|
|
},
|
|
complete: function() {
|
|
unBlock();
|
|
}
|
|
|
|
}); // end of $.ajax()
|
|
}
|
|
|
|
function showPerformanceDetails(d) {
|
|
var resolution = 100;
|
|
|
|
var restOptions = {
|
|
build: $("select#build").val(),
|
|
level: $("select#level").val(),
|
|
platform: $("select#platform").val(),
|
|
resolution: 2,
|
|
x: d.Location.X + (resolution/2),
|
|
y: d.Location.Y + (resolution/2),
|
|
}
|
|
|
|
block();
|
|
|
|
var summary;
|
|
$.ajax({
|
|
url: config.restHost + config.capturePerformanceSummary,
|
|
type: "GET",
|
|
data: restOptions,
|
|
dataType: "json",
|
|
async: true,
|
|
success: function(json, textStatus, jqXHR) {
|
|
summary = json;
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError );
|
|
},
|
|
complete: function() {
|
|
}
|
|
}); // end of summary $.ajax()
|
|
|
|
|
|
$.ajax({
|
|
url: config.restHost + config.capturePerformanceZones,
|
|
type: "GET",
|
|
data: restOptions,
|
|
dataType: "json",
|
|
async: true,
|
|
success: function(json, textStatus, jqXHR) {
|
|
//console.log(json)
|
|
populatePerformanceReport(json, summary);
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError );
|
|
},
|
|
complete: function() {
|
|
var legendText = "Report for Cell with Centre ("
|
|
+ restOptions.x + ", " + restOptions.y + ")";
|
|
$("#performance-overlay fieldset legend").text(legendText);
|
|
$("#performance-overlay").overlay().load();
|
|
unBlock();
|
|
|
|
}
|
|
}); // end of zones $.ajax()
|
|
|
|
}
|
|
|
|
function populatePerformanceReport(data, summary) {
|
|
$("#performance-overlay table").empty();
|
|
|
|
// FPS RESULT
|
|
var fpsSum = summary.FpsInfo;
|
|
$("#fps-results")
|
|
.append(
|
|
$("<tr>")
|
|
.append(
|
|
$("<th>")
|
|
.addClass("title")
|
|
.attr("colspan", 4)
|
|
.text("Fps Result")
|
|
)
|
|
)
|
|
.append(
|
|
$("<tr>")
|
|
.append(
|
|
$("<th>").text("Average (ms)")
|
|
)
|
|
.append(
|
|
$("<th>").text("Max (ms)")
|
|
)
|
|
.append(
|
|
$("<th>").text("Min (ms)")
|
|
)
|
|
.append(
|
|
$("<th>").text("Standard Deviation (ms)")
|
|
)
|
|
)
|
|
.append(
|
|
$("<tr>")
|
|
.append(
|
|
$("<td>")
|
|
.css("color", function() {
|
|
var colour = d3.scale.linear()
|
|
.domain([fpsSum.AverageMin, fpsSum.AverageAverage, fpsSum.AverageMax])
|
|
.range(interpolationColours);
|
|
return colour(data.FpsResult.Average);
|
|
})
|
|
.text(data.FpsResult.Average.toFixed(2) + " (" + fpsSum.AverageAverage.toFixed(2) + ")")
|
|
)
|
|
.append(
|
|
$("<td>")
|
|
.css("color", function() {
|
|
var colour = d3.scale.linear()
|
|
.domain([fpsSum.MaxMin, fpsSum.MaxAverage, fpsSum.MaxMax])
|
|
.range(interpolationColours);
|
|
return colour(data.FpsResult.Max);
|
|
})
|
|
.text(data.FpsResult.Max.toFixed(2) + " (" + fpsSum.MaxAverage.toFixed(2) + ")")
|
|
)
|
|
.append(
|
|
$("<td>")
|
|
.css("color", function() {
|
|
var colour = d3.scale.linear()
|
|
.domain([fpsSum.MinMin, fpsSum.MinAverage, fpsSum.MinMax])
|
|
.range(interpolationColours);
|
|
return colour(data.FpsResult.Min);
|
|
})
|
|
.text(data.FpsResult.Min.toFixed(2) + " (" + fpsSum.MinAverage.toFixed(2) + ")")
|
|
)
|
|
.append(
|
|
$("<td>")
|
|
.text(data.FpsResult.StandardDeviation.toFixed(2))
|
|
)
|
|
);
|
|
|
|
// THREAD RESULTS
|
|
var threadSum = [];
|
|
$.each(summary.ThreadInfo, function(i, threadInfo) {
|
|
threadSum[threadInfo.Name] = threadInfo;
|
|
});
|
|
//console.log(threadSum);
|
|
|
|
$("#thread-results")
|
|
.append(
|
|
$("<tr>")
|
|
.append(
|
|
$("<th>")
|
|
.addClass("title")
|
|
.attr("colspan", 5)
|
|
.text("Thread Results")
|
|
)
|
|
)
|
|
.append(
|
|
$("<tr>")
|
|
.append(
|
|
$("<th>").text("Name")
|
|
)
|
|
.append(
|
|
$("<th>").text("Average (ms)")
|
|
)
|
|
.append(
|
|
$("<th>").text("Max (ms)")
|
|
)
|
|
.append(
|
|
$("<th>").text("Min (ms)")
|
|
)
|
|
.append(
|
|
$("<th>").text("Standard Deviation (ms)")
|
|
)
|
|
);
|
|
|
|
$.each(data.ThreadResults, function(i, threadResult) {
|
|
$("<tr>")
|
|
.append(
|
|
$("<td>").text(threadResult.Name)
|
|
)
|
|
.append(
|
|
$("<td>")
|
|
.css("color", function() {
|
|
var colour = d3.scale.linear()
|
|
.domain([threadSum[threadResult.Name].AverageMin,
|
|
threadSum[threadResult.Name].AverageAverage,
|
|
threadSum[threadResult.Name].AverageMax])
|
|
.range(interpolationColours);
|
|
return colour(threadResult.Average);
|
|
})
|
|
.text(threadResult.Average.toFixed(2) + " (" + threadSum[threadResult.Name].AverageAverage.toFixed(2) + ")")
|
|
)
|
|
.append(
|
|
$("<td>")
|
|
.css("color", function() {
|
|
var colour = d3.scale.linear()
|
|
.domain([threadSum[threadResult.Name].MaxMin,
|
|
threadSum[threadResult.Name].MaxAverage,
|
|
threadSum[threadResult.Name].MaxMax])
|
|
.range(interpolationColours);
|
|
return colour(threadResult.Max);
|
|
})
|
|
.text(threadResult.Max.toFixed(2) + " (" + threadSum[threadResult.Name].MaxAverage.toFixed(2) + ")")
|
|
)
|
|
.append(
|
|
$("<td>")
|
|
.css("color", function() {
|
|
var colour = d3.scale.linear()
|
|
.domain([threadSum[threadResult.Name].MinMin,
|
|
threadSum[threadResult.Name].MinAverage,
|
|
threadSum[threadResult.Name].MinMax])
|
|
.range(interpolationColours);
|
|
return colour(threadResult.Min);
|
|
})
|
|
.text(threadResult.Min.toFixed(2) + " (" + threadSum[threadResult.Name].MinAverage.toFixed(2) + ")")
|
|
)
|
|
.append(
|
|
$("<td>").text(threadResult.StandardDeviation.toFixed(2))
|
|
)
|
|
.appendTo("#thread-results");
|
|
});
|
|
|
|
// CPU RESULTS
|
|
var cpuSum = [];
|
|
$.each(summary.CpuInfo, function(i, cpuInfo) {
|
|
cpuSum[cpuInfo.Name] = cpuInfo;
|
|
});
|
|
|
|
$("#cpu-results")
|
|
.append(
|
|
$("<tr>")
|
|
.append(
|
|
$("<th>")
|
|
.addClass("title")
|
|
.attr("colspan", 6)
|
|
.text("Cpu Results")
|
|
)
|
|
)
|
|
.append(
|
|
$("<tr>")
|
|
.append(
|
|
$("<th>").text("Name")
|
|
)
|
|
.append(
|
|
$("<th>").text("Set")
|
|
)
|
|
.append(
|
|
$("<th>").text("Average (ms)")
|
|
)
|
|
.append(
|
|
$("<th>").text("Max (ms)")
|
|
)
|
|
.append(
|
|
$("<th>").text("Min (ms)")
|
|
)
|
|
.append(
|
|
$("<th>").text("Standard Deviation (ms)")
|
|
)
|
|
);
|
|
|
|
$.each(data.CpuResults, function(i, cpuResult) {
|
|
$("<tr>")
|
|
.append(
|
|
$("<td>").text(cpuResult.Name)
|
|
)
|
|
.append(
|
|
$("<td>").text(cpuResult.Set)
|
|
)
|
|
.append(
|
|
$("<td>")
|
|
.css("color", function() {
|
|
var colour = d3.scale.linear()
|
|
.domain([cpuSum[cpuResult.Name].AverageMin,
|
|
cpuSum[cpuResult.Name].AverageAverage,
|
|
cpuSum[cpuResult.Name].AverageMax])
|
|
.range(interpolationColours);
|
|
return colour(cpuResult.Average);
|
|
})
|
|
.text(cpuResult.Average.toFixed(2) + " (" + cpuSum[cpuResult.Name].AverageAverage.toFixed(2) + ")")
|
|
)
|
|
.append(
|
|
$("<td>")
|
|
.css("color", function() {
|
|
var colour = d3.scale.linear()
|
|
.domain([cpuSum[cpuResult.Name].MaxMin,
|
|
cpuSum[cpuResult.Name].MaxAverage,
|
|
cpuSum[cpuResult.Name].MaxMax])
|
|
.range(interpolationColours);
|
|
return colour(cpuResult.Max);
|
|
})
|
|
.text(cpuResult.Max.toFixed(2) + " (" + cpuSum[cpuResult.Name].MaxAverage.toFixed(2) + ")")
|
|
)
|
|
.append(
|
|
$("<td>")
|
|
.css("color", function() {
|
|
var colour = d3.scale.linear()
|
|
.domain([cpuSum[cpuResult.Name].MinMin,
|
|
cpuSum[cpuResult.Name].MinAverage,
|
|
cpuSum[cpuResult.Name].MinMax])
|
|
.range(interpolationColours);
|
|
return colour(cpuResult.Min);
|
|
})
|
|
.text(cpuResult.Min.toFixed(2) + " (" + cpuSum[cpuResult.Name].MinAverage.toFixed(2) + ")")
|
|
)
|
|
.append(
|
|
$("<td>").text(cpuResult.StandardDeviation.toFixed(2))
|
|
)
|
|
.appendTo("#cpu-results");
|
|
});
|
|
|
|
// Draw List RESULTS
|
|
var drawListSum = [];
|
|
$.each(summary.DrawListInfo, function(i, drawListInfo) {
|
|
drawListSum[drawListInfo.Name] = drawListInfo;
|
|
});
|
|
|
|
$("#draw-list-results")
|
|
.append(
|
|
$("<tr>")
|
|
.append(
|
|
$("<th>")
|
|
.addClass("title")
|
|
.attr("colspan", 5)
|
|
.text("Draw List Results")
|
|
)
|
|
)
|
|
.append(
|
|
$("<tr>")
|
|
.append(
|
|
$("<th>").text("Name")
|
|
)
|
|
.append(
|
|
$("<th>").text("Average (ms)")
|
|
)
|
|
.append(
|
|
$("<th>").text("Max (ms)")
|
|
)
|
|
.append(
|
|
$("<th>").text("Min (ms)")
|
|
)
|
|
.append(
|
|
$("<th>").text("Standard Deviation (ms)")
|
|
)
|
|
);
|
|
|
|
$.each(data.DrawListResults, function(i, drawListResult) {
|
|
$("<tr>")
|
|
.append(
|
|
$("<td>").text(drawListResult.Name)
|
|
)
|
|
.append(
|
|
$("<td>")
|
|
.css("color", function() {
|
|
var colour = d3.scale.linear()
|
|
.domain([drawListSum[drawListResult.Name].AverageMin,
|
|
drawListSum[drawListResult.Name].AverageAverage,
|
|
drawListSum[drawListResult.Name].AverageMax])
|
|
.range(interpolationColours);
|
|
return colour(drawListResult.Average);
|
|
})
|
|
.text(drawListResult.Average + " (" + drawListSum[drawListResult.Name].AverageAverage + ")")
|
|
)
|
|
.append(
|
|
$("<td>")
|
|
.css("color", function() {
|
|
var colour = d3.scale.linear()
|
|
.domain([drawListSum[drawListResult.Name].MaxMin,
|
|
drawListSum[drawListResult.Name].MaxAverage,
|
|
drawListSum[drawListResult.Name].MaxMax])
|
|
.range(interpolationColours);
|
|
return colour(drawListResult.Max);
|
|
})
|
|
.text(drawListResult.Max + " (" + drawListSum[drawListResult.Name].MaxAverage + ")")
|
|
)
|
|
.append(
|
|
$("<td>")
|
|
.css("color", function() {
|
|
var colour = d3.scale.linear()
|
|
.domain([drawListSum[drawListResult.Name].MinMin,
|
|
drawListSum[drawListResult.Name].MinAverage,
|
|
drawListSum[drawListResult.Name].MinMax])
|
|
.range(interpolationColours);
|
|
return colour(drawListResult.Min);
|
|
})
|
|
.text(drawListResult.Min + " (" + drawListSum[drawListResult.Name].MinAverage + ")")
|
|
)
|
|
.append(
|
|
$("<td>").text(drawListResult.StandardDeviation.toFixed(2))
|
|
)
|
|
.appendTo("#draw-list-results");
|
|
});
|
|
|
|
}
|
|
|
|
function drawDeaths() {
|
|
var restUrl = config.restHost + config.buildsPath
|
|
+ $("select#build").val() + "/"
|
|
+ $("select#overlay-group").val() + "/"
|
|
+ $("select#overlay-single").val();
|
|
|
|
var restOptions = {
|
|
level: $("select#level").val(),
|
|
platform: $("select#platform").val(),
|
|
gameType: $("select#deaths-game-type-select").val(),
|
|
}
|
|
|
|
$("select#deaths-list-select").empty();
|
|
|
|
block();
|
|
$.ajax({
|
|
url: restUrl,
|
|
type: "GET",
|
|
data: restOptions,
|
|
dataType: "xml",
|
|
|
|
success: function(xml, textStatus, jqXHR) {
|
|
|
|
var deaths = convertDeathTelemetryStatXml(xml);
|
|
showMsgWhenNoData(deaths);
|
|
|
|
var deathCircles = d3.select("#map svg")
|
|
.append("svg:g")
|
|
.attr("id", "telemetry-overlay")
|
|
.attr("opacity", 0.01);
|
|
|
|
deathCircles
|
|
.selectAll("circle")
|
|
.data(deaths)
|
|
.enter()
|
|
.append("svg:circle")
|
|
.attr("id", function(d, i) {return "circle_" + i;})
|
|
.attr("cx", function(d) {
|
|
return convert2WebXCoord(d.x);
|
|
})
|
|
.attr("cy", function(d) {
|
|
return convert2WebYCoord(d.y);
|
|
})
|
|
.attr("r", 2)
|
|
.attr("fill", config.chartColour1)
|
|
.attr("stroke", config.chartColour3)
|
|
.attr("stroke-width", 0.3)
|
|
.attr("opacity", 0.8)
|
|
.append("title")
|
|
.text(function(d, i) {
|
|
var title = "Location: (x=" + d.x
|
|
+ ", y=" + d.y + ")";
|
|
|
|
if (d.MissionName)
|
|
title += ", \nMission Name: " + d.MissionName;
|
|
if (d.DeathTimestamp && d.MissionStarted)
|
|
title += ", \nTime on Mission: "
|
|
+ formatSecs(dateStringsDiffInSecs(d.DeathTimestamp - d.MissionStarted));
|
|
if (d.WantedLevel)
|
|
title += ", \nWanted Level: " + d.WantedLevel;
|
|
if (d.DeathTimestamp && d.WantedLevelStarted)
|
|
title += ", \nTime with Wanted Level: "
|
|
+ formatSecs(dateStringsDiffInSecs(d.DeathTimestamp - d.WantedLevelStarted));
|
|
if (d.WeaponName)
|
|
title += ", \nWeapon: " + d.WeaponName;
|
|
if (d.KillerIsPlayer == "true")
|
|
title += ", \nThe killer was a player";
|
|
if (d.KillerIsLocalPlayer == "true")
|
|
title += ", \nThe killer was a local player";
|
|
if (d.KillerInVehicle == "true")
|
|
title += ", \nThe killer was on a vehicle";
|
|
if (d.KillerRunning == "true")
|
|
title += ", \nThe killer was running";
|
|
if (d.KillerSprinting == "true")
|
|
title += ", \nThe killer was sprinting";
|
|
if (d.KillerCrouching == "true")
|
|
title += ", \nThe killer was crouching";
|
|
if (d.VictimIsPlayer == "true")
|
|
title += ", \nThe victim was a player";
|
|
if (d.VictimIsLocalPlayer == "true")
|
|
title += ", \nThe victim was a local player";
|
|
if (d.VictimInVehicle == "true")
|
|
title += ", \nThe victim was on a vehicle";
|
|
if (d.VictimRunning == "true")
|
|
title += ", \nThe victim was running";
|
|
if (d.VictimSprinting == "true")
|
|
title += ", \nThe victim was sprinting";
|
|
if (d.VictimCrouching == "true")
|
|
title += ", \nThe victim was crouching";
|
|
|
|
// Populate the html select list
|
|
$("select#deaths-list-select").append(
|
|
$('<option />')
|
|
.text(i+1 + ". Death at (x=" + d.x
|
|
+ ", y=" + d.y + ")")
|
|
.val(i)
|
|
.attr("title", title)
|
|
);
|
|
|
|
return (title);
|
|
});
|
|
|
|
deathCircles
|
|
.transition()
|
|
.attr("opacity", 1);
|
|
|
|
},
|
|
error: function (xhr, ajaxOptions, thrownError) {
|
|
console.error(this.url + "\n" + ajaxOptions + " " + xhr.status + " " + thrownError );
|
|
},
|
|
complete: function() {
|
|
unBlock();
|
|
}
|
|
|
|
}); // end of $.ajax()
|
|
|
|
} // End of drawDeaths
|
|
|
|
function highlightCircle(id) {
|
|
var svg = d3.select("#map svg")
|
|
.selectAll("g#telemetry-overlay");
|
|
|
|
svg.select("circle#circle_" + id)
|
|
.classed("active", true)
|
|
.transition()
|
|
.attr("r", 10)
|
|
//.attr("stroke-width", 3)
|
|
.duration(config.transitionDuration)
|
|
.each("end", function() {
|
|
d3.select(this)
|
|
.classed("active", false)
|
|
.transition()
|
|
.attr("r", 2) // back to normal
|
|
//.attr("stroke-width", 3)
|
|
.delay(config.transitionDelay)
|
|
});
|
|
}
|
|
|
|
function drawSpawnHeatmap() {
|
|
var radius = 2;
|
|
|
|
var pValues = {
|
|
//ForceUrlSuffix: forceUrlSuffix,
|
|
ElementKeyName: "Name",
|
|
ElementValueName: "Value",
|
|
Pairs: {
|
|
"BuildIdentifiers": $("select#build").val(),
|
|
"PlatformNames": $("select#platform").val(),
|
|
"DeathmatchUGCIdentifier": $("select#deathmatch-list").val(),
|
|
"BlockSize": radius,
|
|
"TimeSinceSpawn": $("input#time-since-spawn").val(),
|
|
}
|
|
};
|
|
|
|
var req = new ReportRequest(config.restHost + config.spawnStats,
|
|
"json",
|
|
config.restHost + config.spawnStatsAsync + forceUrlSuffix,
|
|
config.restHost + config.reportsQueryAsync);
|
|
|
|
req.sendSingleAsyncRequest(pValues, handleSpawnResults);
|
|
|
|
function handleSpawnResults(telemetryData) {
|
|
showMsgWhenNoData(telemetryData);
|
|
if (telemetryData.length == 0)
|
|
return;
|
|
|
|
var valueFunc = function(d) {return d.Occurrences};
|
|
var xFunc = function(d) {return d.Location.X};
|
|
var yFunc = function(d) {return d.Location.Y};
|
|
|
|
generateCoolHeatmap(telemetryData, radius, valueFunc, xFunc, yFunc);
|
|
}
|
|
}
|
|
|
|
function generateCoolHeatmap(telemetryData, radius, valueFunc, xFunc, yFunc) {
|
|
/*
|
|
var heatmap = d3.select("#map svg")
|
|
.append("svg:g")
|
|
//.attr("id", "telemetry-overlay")
|
|
.attr("opacity", 0.01);
|
|
|
|
heatmap
|
|
.selectAll("circle")
|
|
.data(telemetryData)
|
|
.enter()
|
|
.append("svg:circle")
|
|
.attr("id", function(d, i) {return "circle_" + i;})
|
|
.attr("cx", function(d) {
|
|
return convert2WebXCoord(xFunc(d));
|
|
})
|
|
.attr("cy", function(d) {
|
|
return convert2WebYCoord(yFunc(d));
|
|
})
|
|
.attr("r", radius/scale)
|
|
.attr("fill", "rgb(0, 255, 0)")
|
|
.attr("opacity", 0.4)
|
|
.append("title")
|
|
.text(function(d) {
|
|
var title = "Centre (x=" + (xFunc(d))
|
|
+ ", y=" + (yFunc(d)) + ")"
|
|
+ "\nOccurences : " + valueFunc(d);
|
|
return (title);
|
|
});
|
|
|
|
heatmap
|
|
.transition()
|
|
.attr("opacity", 1);
|
|
*/
|
|
|
|
// Clean any canvas elements
|
|
$("#map canvas").remove();
|
|
|
|
var config = {
|
|
"radius": 10,
|
|
"element": "map",
|
|
"visible": true,
|
|
"opacity": 60,
|
|
"gradient": { 0: "rgb(0, 255, 0)", 0.5: "yellow", 1: "rgb(255, 0, 0)" }
|
|
};
|
|
|
|
var heatmap = heatmapFactory.create(config);
|
|
|
|
var heatmapData = {
|
|
max: 0,
|
|
data: [],
|
|
};
|
|
|
|
// Var for the max value
|
|
var max = 0;
|
|
// We need to find the rectangle that includes all the points so we can generate only a small
|
|
// heatmap image of the desired area.
|
|
var upperLeft = {x: telemetryData[0].Location.X, y: telemetryData[0].Location.Y};
|
|
var lowerRight = {x: telemetryData[0].Location.X, y: telemetryData[0].Location.Y};
|
|
|
|
$.each(telemetryData, function(i, point) {
|
|
// find the maximum value
|
|
max = (max < valueFunc(point)) ? valueFunc(point) : max;
|
|
// We need to find the upperLeft and lowerRight points in real game coordinates that include all the points
|
|
// upperLeft has minimum X and maximum Y
|
|
upperLeft.x = (xFunc(point) < upperLeft.x) ? xFunc(point) : upperLeft.x;
|
|
upperLeft.y = (yFunc(point) > upperLeft.y) ? yFunc(point) : upperLeft.y;
|
|
// lowerRight has maximum X and minimum or equal Y
|
|
lowerRight.x = (xFunc(point) > lowerRight.x) ? xFunc(point) : lowerRight.x;
|
|
lowerRight.y = (yFunc(point) < lowerRight.y) ? yFunc(point) : lowerRight.y;
|
|
});
|
|
// Save the max value to the heatmap data
|
|
heatmapData["max"] = max;
|
|
// Add the radius to the rectangle corner points
|
|
var margin = 50;
|
|
upperLeft.x -= (radius + margin);
|
|
upperLeft.y += (radius + margin);
|
|
lowerRight.x += (radius + margin);
|
|
lowerRight.y -= (radius + margin);
|
|
|
|
//console.log(max);
|
|
//console.log(upperLeft);
|
|
//console.log(lowerRight);
|
|
|
|
// The width and the height of the heatmap fragment will be
|
|
fragmentWidth = lowerRight.x - upperLeft.x;
|
|
fragmentHeight = upperLeft.y - lowerRight.y;
|
|
//console.log(fragmentWidth);
|
|
//console.log(fragmentHeight);
|
|
|
|
// Crate a new fragment coordinates system where 0.0 is the top left // NEEDS WORK
|
|
// new (0, 0) will be (upperLeft.x, upperLeft.y)
|
|
function convertXtoFragmentCoords(x) {
|
|
// Subtract new (0, 0) from the x coord, upperLeft.x is the minimum x
|
|
return x - upperLeft.x;
|
|
}
|
|
function convertYtoFragmentCoords(y) {
|
|
// Subtract y coord from the new (0, 0), upperLeft.y is the maximum y
|
|
return upperLeft.y - y;
|
|
}
|
|
|
|
$("#map canvas")
|
|
.attr("id", "heatmapjs-canvas")
|
|
.attr("width", fragmentWidth)
|
|
.attr("height", fragmentHeight)
|
|
.css("display", "none");
|
|
|
|
$.each(telemetryData, function(i, point) {
|
|
heatmapData.data.push({
|
|
x: convertXtoFragmentCoords(xFunc(point)),
|
|
y: convertYtoFragmentCoords(yFunc(point)),
|
|
count: valueFunc(point)});
|
|
});
|
|
heatmap.store.setDataSet(heatmapData);
|
|
//console.log(heatmapData);
|
|
|
|
// Save the canvas to a file object as png image
|
|
var canvas = document.getElementById("heatmapjs-canvas");
|
|
var image = canvas.toDataURL("image/png");
|
|
//window.location = image;
|
|
|
|
// Add the scaled image to the correct position on the svg map (use the previously calculated upperLeft point)
|
|
d3.select("#map svg")
|
|
.append("svg:g")
|
|
.attr("id", "telemetry-overlay")
|
|
.append("svg:image")
|
|
.attr("xlink:href", image)
|
|
.attr("width", fragmentWidth/project.map.scale)
|
|
.attr("height", fragmentHeight/project.map.scale)
|
|
.attr("x", function() {return convert2WebXCoord(upperLeft.x)})
|
|
//.attr("x", convert2WebXCoord(upperLeft.x))
|
|
.attr("y", function() {return convert2WebYCoord(upperLeft.y)});
|
|
}
|
|
// end of generateCoolHeatmap
|
|
|
|
function removeOverlay() {
|
|
d3.select("#map svg")
|
|
.selectAll("g#telemetry-overlay")
|
|
.transition()
|
|
.attr("opacity", 0.01)
|
|
.remove();
|
|
}
|
|
|
|
function generateCustomOverlay(useCached) {
|
|
removeOverlay();
|
|
|
|
if ($("#filter-force").is(":checked"))
|
|
forceUrlSuffix = config.reportForceSuffix;
|
|
else
|
|
forceUrlSuffix = "";
|
|
//console.log(forceUrlSuffix);
|
|
|
|
if ($("select#overlay-group").val() == $("select#overlay-group option:eq(1)").val()) { // == "Telemetry Group"
|
|
if ($("select#overlay-single").val() == $("select#overlay-single option:eq(0)").val()) { // == "Fps"
|
|
drawFpsHeatmap(useCached);
|
|
}
|
|
else if ($("select#overlay-single").val() == $("select#overlay-single option:eq(1)").val()) { // == "ShapeTest"
|
|
drawShapeTestHeatmap(useCached);
|
|
}
|
|
else if ($("select#overlay-single").val() == $("select#overlay-single option:eq(2)").val()) { // == "Shortfall"
|
|
drawShortfallHeatmap(useCached);
|
|
}
|
|
else if ($("select#overlay-single").val() == $("select#overlay-single option:eq(3)").val()) { // == "Cps"
|
|
drawCpsHeatmap(useCached);
|
|
}
|
|
else if ($("select#overlay-single").val() == $("select#overlay-single option:eq(4)").val()) { // == "Deaths"
|
|
drawDeaths(useCached);
|
|
}
|
|
else if ($("select#overlay-single").val() == $("select#overlay-single option:eq(5)").val()) { // == "Spawns"
|
|
drawSpawnHeatmap(useCached);
|
|
}
|
|
}
|
|
}
|
|
|
|
function toggleOverlayOptions(selectedValue) {
|
|
$(".overlay-options").hide();
|
|
var selectedOverlayID;
|
|
|
|
if (selectedValue == $("select#overlay-single option:eq(0)").val()) {// == "FPS"
|
|
$("#fps-overlay-options").show("blind", {}, "slow");
|
|
selectedOverlayID = "fps-overlay-options";
|
|
}
|
|
else if (selectedValue == $("select#overlay-single option:eq(1)").val()) {// == "PST"
|
|
$("#pst-overlay-options").show("blind", {}, "slow");
|
|
selectedOverlayID = "pst-overlay-options";
|
|
}
|
|
else if (selectedValue == $("select#overlay-single option:eq(2)").val()) {// == "MSF"
|
|
$("#msf-overlay-options").show("blind", {}, "slow");
|
|
selectedOverlayID = "msf-overlay-options";
|
|
}
|
|
else if (selectedValue == $("select#overlay-single option:eq(3)").val()) {// == "CPS"
|
|
$("#cps-overlay-options").show("blind", {}, "slow");
|
|
}
|
|
else if (selectedValue == $("select#overlay-single option:eq(4)").val()) { // == "Deaths"
|
|
$("#deaths-overlay-options").show("blind", {}, "slow");
|
|
}
|
|
else if (selectedValue == $("select#overlay-single option:eq(5)").val()) { // == "Spawn"
|
|
$("#spawn-overlay-options").show("blind", {}, "slow");
|
|
}
|
|
|
|
if (selectedOverlayID) {
|
|
var defaultMinHue = 0,
|
|
defaultMaxHue = 240,
|
|
defaultMinHueSlider = 0,
|
|
defaultMaxHueSlider = 120;
|
|
|
|
$("#" + selectedOverlayID + " div.heatmap-slider-placeholder").slider({
|
|
range: true,
|
|
min: defaultMinHue,
|
|
max: defaultMaxHue,
|
|
values: [defaultMinHueSlider, defaultMaxHueSlider],
|
|
stop: function(event, ui ) { // fire when mouse is released
|
|
generateHeatmapGradient(selectedOverlayID + " span.heatmap-gradient",
|
|
//ui.values[0], ui.values[1]);
|
|
ui.values[1], ui.values[0]);
|
|
generateCustomOverlay(true);
|
|
}
|
|
});
|
|
|
|
$("#" + selectedOverlayID + " div.value-slider").slider({
|
|
range: true,
|
|
min: 0,
|
|
max: 0,
|
|
values: [0, 0],
|
|
stop: function(event, ui ) { // fire when mouse is released
|
|
generateCustomOverlay(true);
|
|
}
|
|
});
|
|
|
|
$("#" + selectedOverlayID + " div.threshold-slider").slider({
|
|
min: 0,
|
|
max: 0,
|
|
value: 0,
|
|
stop: function(event, ui ) { // fire when mouse is released
|
|
$(this).next().text(ui.value.toFixed(2));
|
|
generateCustomOverlay(true);
|
|
}
|
|
});
|
|
|
|
generateHeatmapGradient(selectedOverlayID + " span.heatmap-slider", defaultMinHue, defaultMaxHue);
|
|
|
|
generateHeatmapGradient(selectedOverlayID + " span.heatmap-gradient",
|
|
defaultMaxHueSlider, defaultMinHueSlider);
|
|
}
|
|
}
|
|
|
|
function showMsgWhenNoData(array) {
|
|
if (array.length < 1)
|
|
Sexy.alert(config.noDataMapText);
|
|
}
|
|
|
|
function generateHeatmapGradient(elementID, minHue, maxHue) {
|
|
var canvas = $("#" + elementID + " canvas")[0];
|
|
var context = canvas.getContext("2d");
|
|
|
|
context.rect(0, 0, canvas.width, canvas.height);
|
|
|
|
// add linear gradient
|
|
var grd = context.createLinearGradient(0, 0, canvas.width, 0);
|
|
|
|
var s = 0.9, v = 0.9;
|
|
var hueStep = (maxHue - minHue) / 5;
|
|
|
|
grd.addColorStop(0, hsv2hex(minHue, s, v));
|
|
grd.addColorStop(0.167, hsv2hex(minHue+hueStep, s, v));
|
|
grd.addColorStop(0.333, hsv2hex(minHue+2*hueStep, s, v));
|
|
grd.addColorStop(0.5, hsv2hex(minHue+3*hueStep, s, v));
|
|
grd.addColorStop(0.667, hsv2hex(minHue+4*hueStep, s, v));
|
|
grd.addColorStop(0.833, hsv2hex(minHue+5*hueStep, s, v));
|
|
grd.addColorStop(1, hsv2hex(maxHue, s, v));
|
|
|
|
context.fillStyle = grd;
|
|
context.fill();
|
|
}
|
|
|
|
function getColourInterpolator(minVal, maxVal, minHue, maxHue) {
|
|
// copying Michael Taschler's code of interpolation
|
|
|
|
return function (val) {
|
|
// Give the values outside the limits the limit colours
|
|
if (val < minVal)
|
|
val = minVal;
|
|
else if (val > maxVal)
|
|
val = maxVal;
|
|
|
|
// 0.0 to 1.0 scale convertion
|
|
val -= minVal;
|
|
if ((maxVal - minVal) != 0) // avoid division by zero
|
|
val /= (maxVal - minVal);
|
|
else
|
|
val = 0;
|
|
|
|
var lowHue = minHue / 360.0;
|
|
var highHue = maxHue / 360.0;
|
|
var diffHue = highHue - lowHue;
|
|
|
|
var h = (lowHue + (val * diffHue)) * 360;
|
|
var s = 0.9;
|
|
var v = 0.9;
|
|
|
|
return hsv2hex(h, s, v);
|
|
}
|
|
}
|
|
|
|
function hsv2hex(h, s, v) {
|
|
// Hue stays the same
|
|
// Saturation is very different between the two color spaces
|
|
// If (2-s)*v < 1 set it to s*v/((2-s)*v)
|
|
// Otherwise s*v/(2-(2-s)*v)
|
|
// Conditional is not operating with hue, it is reassigned!
|
|
s = (s * v) / ((((2-s) * v) < 1) ? ((2-s) * v) : 2-((2-s) * v));
|
|
l = (2-s)*v/2; // Lightness is (2-s)*v/2
|
|
|
|
return d3.hsl(h, s, l).toString();
|
|
}
|
|
|
|
// All these convertXml() functions will be removed once the data will be returned in json
|
|
/*
|
|
function convertBuildsXml(xml) {
|
|
var elementsArray = [];
|
|
var elements = xml.documentElement.getElementsByTagName("Build");
|
|
for (var i=0; i<elements.length; i++) {
|
|
var build = {
|
|
Id: parseInt(elements[i].childNodes[0].childNodes[0].nodeValue),
|
|
CreatedOn: elements[i].childNodes[1].childNodes[0].nodeValue,
|
|
ModifiedOn: elements[i].childNodes[2].childNodes[0].nodeValue,
|
|
Identifier: parseFloat(elements[i].childNodes[3].childNodes[0].nodeValue),
|
|
HasAssetStats: elements[i].childNodes[4].childNodes[0].nodeValue,
|
|
HasProcessedStats: elements[i].childNodes[5].childNodes[0].nodeValue,
|
|
HasAutomatedEverythingStats: elements[i].childNodes[6].childNodes[0].nodeValue,
|
|
HasAutomatedMapOnlyStats: elements[i].childNodes[7].childNodes[0].nodeValue,
|
|
HasMagDemoStats: elements[i].childNodes[8].childNodes[0].nodeValue,
|
|
};
|
|
elementsArray.push(build);
|
|
}
|
|
return elementsArray;
|
|
}
|
|
*/
|
|
|
|
function convertResolutionsXml(xml) {
|
|
var elementsArray = [];
|
|
var elements = xml.documentElement.getElementsByTagName("ProcessedStatResolution");
|
|
for (var i=0; i<elements.length; i++) {
|
|
var resolution = {
|
|
Id: parseInt(elements[i].childNodes[0].childNodes[0].nodeValue),
|
|
CreatedOn: elements[i].childNodes[1].childNodes[0].nodeValue,
|
|
BlockSize: parseInt(elements[i].childNodes[2].childNodes[0].nodeValue),
|
|
};
|
|
elementsArray.push(resolution);
|
|
}
|
|
return elementsArray;
|
|
}
|
|
|
|
/*
|
|
// Use the generic ones instead
|
|
|
|
function convertPlatformsXml(xml) {
|
|
var elementsArray = [];
|
|
var elements = xml.documentElement.getElementsByTagName("Platform");
|
|
for (var i=0; i<elements.length; i++) {
|
|
var platform = {
|
|
Value: elements[i].getAttribute("Value"),
|
|
};
|
|
elementsArray.push(platform);
|
|
}
|
|
return elementsArray;
|
|
}
|
|
|
|
function convertGametypesXml(xml) {
|
|
var elementsArray = [];
|
|
var elements = xml.documentElement.getElementsByTagName("GameType");
|
|
for (var i=0; i<elements.length; i++) {
|
|
var gametype = {
|
|
Value: elements[i].getAttribute("Value"),
|
|
};
|
|
elementsArray.push(gametype);
|
|
}
|
|
return elementsArray;
|
|
}
|
|
*/
|
|
|
|
function convertBuildConfigsXml(xml) {
|
|
var elementsArray = [];
|
|
|
|
$(xml).find("BuildConfig").each(function(){
|
|
var buildConfig = {
|
|
Value: $(this).find("Value").text()
|
|
};
|
|
elementsArray.push(buildConfig);
|
|
});
|
|
|
|
return elementsArray;
|
|
}
|
|
|
|
function convertDrawListXml(xml) {
|
|
var elementsArray = [];
|
|
|
|
$(xml).find("DrawList").each(function(){
|
|
var element = {
|
|
Id: $(this).find("Id").text(),
|
|
CreatedOn: $(this).find("CreatedOn").text(),
|
|
ModifiedOn: $(this).find("ModifiedOn").text(),
|
|
Name: $(this).find("Name").text(),
|
|
Hash: $(this).find("Hash").text(),
|
|
};
|
|
elementsArray.push(element);
|
|
});
|
|
|
|
return elementsArray;
|
|
}
|
|
|
|
function convertDeathTelemetryStatXml(xml) {
|
|
var elementsArray = [];
|
|
|
|
// Using jquery to parse xml
|
|
$(xml).find("DeathTelemetryStat").each(function() {
|
|
var element = {
|
|
x: parseInt($(this).find("Location").attr("x")),
|
|
y: parseInt($(this).find("Location").attr("y")),
|
|
WeaponName: $(this).find("WeaponName").text(),
|
|
WeaponHash: $(this).find("WeaponHash").text(),
|
|
KillerIsPlayer: $(this).find("KillerIsPlayer").text(),
|
|
KillerIsLocalPlayer: $(this).find("KillerIsLocalPlayer").text(),
|
|
KillerInVehicle: $(this).find("KillerInVehicle").text(),
|
|
KillerRunning: $(this).find("KillerRunning").text(),
|
|
KillerSprinting: $(this).find("KillerSprinting").text(),
|
|
KillerCrouching: $(this).find("KillerCrouching").text(),
|
|
VictimIsPlayer: $(this).find("VictimIsPlayer").text(),
|
|
VictimIsLocalPlayer: $(this).find("VictimIsLocalPlayer").text(),
|
|
VictimInVehicle: $(this).find("VictimInVehicle").text(),
|
|
VictimRunning: $(this).find("VictimRunning").text(),
|
|
VictimSprinting: $(this).find("VictimSprinting").text(),
|
|
VictimCrouching: $(this).find("VictimCrouching").text(),
|
|
MissionName: $(this).find("MissionName").text(),
|
|
MissionStarted: $(this).find("MissionStarted").text(),
|
|
MissionEnded: $(this).find("MissionEnded").text(),
|
|
DeathTimestamp: $(this).find("DeathTimestamp").text(),
|
|
WantedLevel: $(this).find("WantedLevel").text(),
|
|
WantedLevelStarted: $(this).find("WantedLevelStarted").text(),
|
|
WantedLevelEnded: $(this).find("WantedLevelEnded").text(),
|
|
};
|
|
elementsArray.push(element);
|
|
});
|
|
|
|
return elementsArray;
|
|
}
|
|
|
|
//End of convertXml group of functions
|
|
|