summaryrefslogtreecommitdiffstats
path: root/web/topchanges/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'web/topchanges/main.js')
-rw-r--r--web/topchanges/main.js422
1 files changed, 422 insertions, 0 deletions
diff --git a/web/topchanges/main.js b/web/topchanges/main.js
new file mode 100644
index 0000000..cb9a208
--- /dev/null
+++ b/web/topchanges/main.js
@@ -0,0 +1,422 @@
+// --- BEGIN Global variables -----------------------------------
+
+var limit = null; // Size of top score list (a "Top 10" list has limit=10 etc.)
+
+// Id-to-name mappings:
+var hosts = null;
+var platforms = null;
+var branches = null;
+var sha1s = null;
+var benchmarks = null;
+var metrics = null;
+
+// Test cases with changes:
+var testCases = null;
+
+// --- END Global variables -------------------------------------
+
+function toggleTestCaseFilter() {
+ var divObj_hidden = $("#div_testCaseFilter_hidden");
+ var divObj_shown = $("#div_testCaseFilter_shown");
+ if (divObj_shown.css("display") == "none") {
+ divObj_shown.css("display", "block");
+ divObj_hidden.css("display", "none");
+ } else {
+ divObj_shown.css("display", "none");
+ divObj_hidden.css("display", "block");
+ }
+}
+
+
+function updateTestCaseTable() {
+
+ // Clear table:
+ $("#test_cases tr").remove();
+
+ // Populate table:
+
+ var nc = 8; // # of columns
+ var nr = Math.ceil(testCases.length / nc); // # of rows
+ var c1 = testCases.length % nc; // lowest column index for empty bottom cell
+
+ var html = "";
+ for (r = 0; r < nr; ++r) {
+ if ((r < (nr - 1)) || (nc > 1))
+ html += "<tr>";
+ for (c = 0; c < nc; ++c) {
+ if ((r == (nr - 1)) && (c >= c1) && (!(nc == 1))) {
+ html += "<td></td>"; // Fill in empty bottom cell
+ } else {
+ var index = -1;
+ if (c <= c1)
+ index = r + c * nr;
+ else
+ index = r + c1 * nr + (c - c1) * (nr - 1);
+
+ var name = testCases[index];
+ html += "<td style=\"white-space: nowrap\">";
+ html += "<input type=\"checkbox\" id=\"tc" + index + "\" " +
+ "name=\"" + name + "\"/>";
+ html += "<label for=\"tc" + index + "\">" + name +
+ "</label>";
+ html += "</td>";
+ }
+ }
+ if ((r < (nr - 1)) || (nc > 1))
+ html += "</tr>";
+ }
+
+ $("#test_cases").append(html);
+}
+
+
+// ### 2 B DOCUMENTED!
+function timeSeriesURL(
+ database, hostId, platformId, branchId, sha1Id, benchmarkId, metricId,
+ difftol, durtolmin, durtolmax) {
+
+ query = "?db=" + database;
+ query += "&host=" + encodeURIComponent(hosts[hostId]);
+ query += "&platform=" + encodeURIComponent(platforms[platformId]);
+ query += "&branch=" + encodeURIComponent(branches[branchId]);
+ query += "&sha11=earliest"; // invalid SHA-1 specifies infinite startpoint
+ query += "&sha12=latest"; // invalid SHA-1 specifies infinite endpoint
+ query += "&sha1_sel=" + sha1s[sha1Id];
+ query += "&benchmark=" + encodeURIComponent(benchmarks[benchmarkId]);
+ query += "&metric=" + encodeURIComponent(metrics[metricId]);
+ query += "&difftol=" + difftol;
+ query += "&durtolmin=" + durtolmin;
+ query += "&durtolmax=" + durtolmax;
+
+ url = "http://" + location.host + "/bm2/analysis/tsbm.shtml" + query;
+ return url;
+}
+
+
+// Loads a main table from the database.
+function loadMainTable(tableName, regressions, last, timescope, premature) {
+
+ var tableSel = "#" + tableName;
+
+ updateStatus("fetching top changes ...", true);
+
+ //var database = $('#database').val();
+ var database = "bm"; // ### Hardcoded for now!
+ // ### The following tolerances are hardcoded for now. They are assumed
+ // to match the tolerances used for computing the 'change' table
+ // (see updatechanges.py script)!
+ var difftol = 1.1;
+ var durtolmin = 3;
+ var durtolmax = 10;
+
+ query = "?db=" + database;
+ query += "&cmd=topchanges";
+ query += "&regressions=" + (regressions ? 1 : 0);
+ query += "&last=" + (last ? 1 : 0);
+ query += "&timescope=" + timescope;
+ query += "&premature=" + (premature ? 1 : 0);
+ query += "&limit=" + limit;
+
+ // Add test case filter:
+ testCaseFilter = "";
+ $("#test_cases input").each(function() {
+ if (this.checked) {
+ testCaseFilter += " " + this.name;
+ }
+ });
+ query += "&testcasefilter=" + testCaseFilter;
+
+ url = "http://" + location.host + "/cgi-bin/getstatswrapper" + query;
+ //alert("url: >" + url + "<");
+
+ $.ajax({
+ url: url,
+ type: "GET",
+ dataType: "json",
+
+ success: function(data, textStatus, request) {
+ if (request.readyState == 4) {
+ if (request.status == 200) {
+
+ if (data.error != null) {
+ updateStatus(
+ "fetching top changes ... failed: " +
+ data.error, false);
+ return
+ }
+
+ updateStatus("fetching top changes ... done", false);
+ updateStatus("", false);
+
+ // Remove all rows below the header ...
+ $(tableSel + " tr:gt(0)").remove();
+
+ // Insert new rows ...
+ contexts = data.contexts;
+ html = "";
+ for (i = 0; i < contexts.length; ++i) {
+ context = contexts[i];
+
+ var hostId = context.hostId;
+ var platformId = context.platformId;
+ var branchId = context.branchId;
+
+ html += "<tr>";
+
+ html += "<td style=\"white-space: nowrap\">" +
+ hosts[hostId] + "</td>";
+ html += "<td style=\"white-space: nowrap\">" +
+ platforms[platformId] + "</td>";
+ html += "<td style=\"white-space: nowrap\">" +
+ branches[branchId] + "</td>";
+
+ // Fill in scores:
+ for (j = 0; j < context.topchanges.length; ++j) {
+ var tc = context.topchanges[j];
+ var benchmarkId = tc[0];
+ var metricId = tc[1];
+ var sha1Id = tc[2];
+ var timestamp = tc[3];
+ var score = tc[4];
+ var bgColor = scoreColor(score, data.regressions);
+ html += "<td style=\"background-color:" +
+ bgColor + "\">";
+ html += "<a href=\"" +
+ timeSeriesURL(
+ database, hostId, platformId, branchId,
+ sha1Id, benchmarkId, metricId, difftol,
+ durtolmin, durtolmax) +
+ "\"" +
+ " target=\"_blank\" style=\"" +
+ "text-decoration:none; color:black; " +
+ "display:block\">";
+ html += score;
+ html += "</a>";
+
+ html += "</td>";
+ }
+
+ // Fill in missing scores:
+ for (j = context.topchanges.length; j < limit; ++j) {
+ html +=
+ "<td style=\"background-color:#bbb\"></td>";
+ }
+
+ html += "</tr>";
+ }
+
+ $(tableSel + " > tbody:last").append(html);
+ $(tableSel).trigger("update");
+ if (html != "") // hm ... why is this test necessary?
+ $(tableSel).trigger("appendCache");
+ }
+ }
+ },
+
+ error: function(request, textStatus, errorThrown) {
+ descr = errorThrown;
+ if (errorThrown == null) {
+ descr = "undefined error - is the server down?";
+ }
+ updateStatus(
+ "fetching top changes ... error: " + descr, false);
+ }
+
+ // complete: function(request, textStatus) {
+ // alert("complete; request.status: " + request.status)
+ // }
+
+ });
+
+ return false;
+}
+
+
+// Updates the main table based on the current change type.
+function updateMainTable() {
+ var pctTag = $("#primary_change_type option:selected").attr("tag");
+ var sctTag = $("#secondary_change_type option:selected").attr("tag");
+ var pmtTag =
+ ($("#incl_premature_changes:checked").length == 1) ? "_pmt" : "";
+ var tableName = "mt_" + pctTag + "_" + sctTag + pmtTag;
+ var divName = "div_" + tableName;
+ // ### NOTE: tableName and divName unused for now. Later they may be used
+ // for caching based on multiple main tables (of which only one is shown
+ // at a time).
+
+ // Hide all tables but the current one:
+ // ### NOTE: Unused for now (see above)
+ // $('div[id^="div_mt_"]').css("display", "none");
+ // $("#" + divName).css("display", "block");
+
+ var regressions = (pctTag == "regr");
+ var last = (sctTag == "last");
+ var sctTag_int = parseInt(sctTag);
+ var timescope =
+ ((sctTag == "all") || (isNaN(sctTag_int))) ? -1 : sctTag_int;
+ var premature = (pmtTag == "_pmt");
+
+ // Load the table from the database if necessary:
+ // if ($("#" + tableName + " tr").length == 1) {
+ // // The table for this change type is empty
+ // // (except for header row), so populate it from the database:
+ // loadMainTable(tableName, regressions, last, timescope, premature)
+ // }
+
+ // ### Just reload the only main table for now (later a caching scheme
+ // should be implemented):
+ loadMainTable("main_table", regressions, last, timescope, premature)
+}
+
+
+function fetchNameMappings() {
+ updateStatus("fetching name mappings ...", true);
+
+ //database = $('#database').val();
+ database = "bm"; // ### Hardcoded for now!
+
+ query = "?db=" + database;
+ query += "&cmd=namemappings";
+
+ url = "http://" + location.host + "/cgi-bin/getstatswrapper" + query;
+ //alert("url: >" + url + "<");
+
+ $.ajax({
+ url: url,
+ type: "GET",
+ dataType: "json",
+
+ success: function(data, textStatus, request) {
+ if (request.readyState == 4) {
+ if (request.status == 200) {
+
+ if (data.error != null) {
+ updateStatus(
+ "fetching name mappings ... failed: " +
+ data.error, false);
+ return
+ }
+
+ updateStatus("fetching name mappings ... done", false);
+ updateStatus("", false);
+
+ hosts = data.hosts;
+ platforms = data.platforms;
+ branches = data.branches;
+ sha1s = data.sha1s;
+ benchmarks = data.benchmarks;
+ metrics = data.metrics;
+
+ updateTestCaseTable();
+ updateMainTable();
+ }
+ }
+ },
+
+ error: function(request, textStatus, errorThrown) {
+ descr = errorThrown;
+ if (errorThrown == null) {
+ descr = "undefined error - is the server down?";
+ }
+ updateStatus(
+ "fetching name mappings ... error: " + descr, false);
+ }
+
+ // complete: function(request, textStatus) {
+ // alert("complete; request.status: " + request.status)
+ // }
+
+ });
+
+ return false;
+}
+
+
+function fetchTestCases() {
+ updateStatus("fetching test cases ...", true);
+
+ //database = $('#database').val();
+ database = "bm"; // ### Hardcoded for now!
+
+ query = "?db=" + database;
+ query += "&cmd=testcaseswithchanges";
+
+ url = "http://" + location.host + "/cgi-bin/getstatswrapper" + query;
+ //alert("url: >" + url + "<");
+
+ $.ajax({
+ url: url,
+ type: "GET",
+ dataType: "json",
+
+ success: function(data, textStatus, request) {
+ if (request.readyState == 4) {
+ if (request.status == 200) {
+
+ if (data.error != null) {
+ updateStatus(
+ "fetching test cases ... failed: " +
+ data.error, false);
+ return
+ }
+
+ updateStatus("fetching test cases ... done", false);
+ updateStatus("", false);
+
+ testCases = data.testCases;
+
+ fetchNameMappings();
+ }
+ }
+ },
+
+ error: function(request, textStatus, errorThrown) {
+ descr = errorThrown;
+ if (errorThrown == null) {
+ descr = "undefined error - is the server down?";
+ }
+ updateStatus(
+ "fetching test cases ... error: " + descr, false);
+ }
+
+ // complete: function(request, textStatus) {
+ // alert("complete; request.status: " + request.status)
+ // }
+
+ });
+
+ return false;
+}
+
+
+$(document).ready(function() {
+
+ initTablesorter();
+
+ // Initialize main table:
+ $("#main_table").tablesorter({
+ headers: {
+ 3: { sorter: "mixed_numeric_desc_before_missing" }, // rank pos 0
+ 4: { sorter: false }, // 1
+ 5: { sorter: false }, // 2
+ 6: { sorter: false }, // 3
+ 7: { sorter: false }, // 4
+ 8: { sorter: false }, // 5
+ 9: { sorter: false }, // 6
+ 10: { sorter: false }, // 7
+ 11: { sorter: false }, // 8
+ 12: { sorter: false } // 9
+ }
+ });
+
+ // Initialize change type:
+ $("#primary_change_type option[singular_name='regression']").attr(
+ "selected", true);
+ $("#incl_premature_changes").attr("checked", false)
+
+ // Deduce the limit directly from the static HTML of the main table:
+ // (subtract 3 for the Host, Platform, and Branch columns)
+ limit = $("#main_table th").length - 3;
+
+ fetchTestCases();
+});