diff options
Diffstat (limited to 'web/topchanges/main.js')
-rw-r--r-- | web/topchanges/main.js | 422 |
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 += "®ressions=" + (regressions ? 1 : 0); + query += "&last=" + (last ? 1 : 0); + query += "×cope=" + 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(); +}); |