| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 6 * Factory function to create a View for "peak hours". | |
| 7 * | |
| 8 * This display of the data shows tree closure/open totals during peak hours in | |
| 9 * various time zones. | |
| 10 */ | |
| 11 var CreatePeakHoursView; | |
| 12 | |
| 13 // ----------------------------------------------------------------------------- | |
| 14 // Private implementation | |
| 15 // ----------------------------------------------------------------------------- | |
| 16 | |
| 17 (function() { | |
| 18 | |
| 19 CreatePeakHoursView = function(timeRange, entries) { | |
| 20 return new PeakHoursView(timeRange, entries); | |
| 21 } | |
| 22 | |
| 23 function PeakHoursView(timeRange, entries) { | |
| 24 Draw(entries, timeRange); | |
| 25 } | |
| 26 | |
| 27 PeakHoursView.prototype.Show = function(visible) { | |
| 28 gViewerApp.ShowViewContentAndTabArea("peak", visible); | |
| 29 } | |
| 30 | |
| 31 /** | |
| 32 * Draws the peak hours chart for all days in |timeRange|. | |
| 33 * @param {array<Entry>} entries | |
| 34 * @param {TimeRange} timeRange | |
| 35 */ | |
| 36 function Draw(entries, timeRange) { | |
| 37 var utcOffsetsMillis = { | |
| 38 // Please keep this ordered by UTC offset. | |
| 39 // If you extend this list, you need to adjust column widths in | |
| 40 // AddPeakColumn() and on the status_viewer.html page. | |
| 41 MTV: -7 * DateUtil.MILLIS_PER_HOUR, // UTC-7 -- Mountain View | |
| 42 NYC: -4 * DateUtil.MILLIS_PER_HOUR, // UTC-4 -- New York | |
| 43 CET: 1 * DateUtil.MILLIS_PER_HOUR, // UTC+1 -- Denmark | |
| 44 TOK: 9 * DateUtil.MILLIS_PER_HOUR // UTC+9 -- Tokyo | |
| 45 }; | |
| 46 var graphCSV = []; | |
| 47 | |
| 48 // Find which is the minimum and maximum. | |
| 49 var minUTCOffsetMillis = utcOffsetsMillis.MTV; | |
| 50 var maxUTCOffsetMillis = utcOffsetsMillis.MTV; | |
| 51 | |
| 52 for (var timezone in utcOffsetsMillis) { | |
| 53 var offset = utcOffsetsMillis[timezone]; | |
| 54 minUTCOffsetMillis = Math.min(minUTCOffsetMillis, offset); | |
| 55 maxUTCOffsetMillis = Math.max(maxUTCOffsetMillis, offset); | |
| 56 } | |
| 57 | |
| 58 // Set the graph csv header: "Date,MTV,NYC,CET,TOK\n". | |
| 59 graphCSV.push("Date"); | |
| 60 for (var timezone in utcOffsetsMillis) { | |
| 61 graphCSV.push(","); | |
| 62 graphCSV.push(timezone); | |
| 63 } | |
| 64 graphCSV.push("\n"); | |
| 65 | |
| 66 // Figure out what days we touch. | |
| 67 // | |
| 68 // Note that we have to extend the time range by the max and | |
| 69 // minimum offsets, since those timezones may be on the next/previous | |
| 70 // day! | |
| 71 var days = DateUtil.GetUTCDaysInRange( | |
| 72 new TimeRange(timeRange.startTime + maxUTCOffsetMillis, | |
| 73 timeRange.endTime + minUTCOffsetMillis)); | |
| 74 | |
| 75 var tbody = document.getElementById("peak_tbody"); | |
| 76 // Clear anything already present in the output table. | |
| 77 tbody.innerHTML = ""; | |
| 78 | |
| 79 // Draw the rows for each day worth of data. | |
| 80 for (var i = 0; i < days.length; ++i) { | |
| 81 var day = days[i]; | |
| 82 DrawDay(tbody, entries, day, utcOffsetsMillis, graphCSV); | |
| 83 } | |
| 84 | |
| 85 // Draw a graph with the csv data across all dates. | |
| 86 // Dygraph docs at http://danvk.org/dygraphs/ | |
| 87 var peakGraph = | |
| 88 new Dygraph(document.getElementById("peak_dygraph"), | |
| 89 graphCSV.join(""), | |
| 90 { | |
| 91 rollPeriod: 1, | |
| 92 showRoller: true, | |
| 93 axisLabelFontSize: 11, | |
| 94 includeZero: true, | |
| 95 colors: ["red", "orange", "blue", "LightSkyBlue"], | |
| 96 strokeWidth: 3, | |
| 97 labelsDiv: document.getElementById("peak_dygraph_legend"), | |
| 98 labelsSeparateLines: true, | |
| 99 }); | |
| 100 } | |
| 101 | |
| 102 /** | |
| 103 * Draws a specific day's row in the peak hours chart. | |
| 104 * @parm {DOMNode} tbody | |
| 105 * @param {array<Entry>} entries | |
| 106 * @param {TimeRange} day | |
| 107 * @param {dict} utcOffsetsMillis | |
| 108 * @param {array} graphCSV | |
| 109 */ | |
| 110 function DrawDay(tbody, entries, utcDay, utcOffsetsMillis, graphCSV) { | |
| 111 var tr = DomUtil.AddNode(tbody, "tr"); | |
| 112 | |
| 113 | |
| 114 var tdForDayName = DomUtil.AddNode(tr, "td"); | |
| 115 | |
| 116 DrawUTCDayNameColumn(utcDay, tdForDayName); | |
| 117 // Start each graphCSV row with a date like "2010/08/01". | |
| 118 graphCSV.push(tdForDayName.innerText); | |
| 119 | |
| 120 var tableTd = DomUtil.AddNode(tr, "td"); | |
| 121 | |
| 122 tableTd.width = "100%"; | |
| 123 | |
| 124 var table = DomUtil.AddNode(tableTd, "table"); | |
| 125 table.cellSpacing = 0; | |
| 126 table.cellPadding = 0; | |
| 127 table.width = "100%"; | |
| 128 | |
| 129 var tr = DomUtil.AddNode(table, "tr"); | |
| 130 | |
| 131 for (var timezone in utcOffsetsMillis) { | |
| 132 AddPeakColumn(tr, | |
| 133 entries, | |
| 134 utcDay, | |
| 135 utcOffsetsMillis[timezone], | |
| 136 graphCSV); | |
| 137 } | |
| 138 graphCSV.push("\n"); | |
| 139 } | |
| 140 | |
| 141 /** | |
| 142 * @returns {StatusTotals} | |
| 143 */ | |
| 144 function GetStateCountsInRange(runs, timeRange) { | |
| 145 var statusTotalsSeconds = new StatusTotals(); | |
| 146 | |
| 147 var y1 = timeRange.startTime; | |
| 148 var y2 = timeRange.endTime; | |
| 149 | |
| 150 for (var i = 0; i < runs.length; ++i) { | |
| 151 var run = runs[i]; | |
| 152 | |
| 153 // Basically we have two boxes (x and y), and need to find the overlap. | |
| 154 var x1 = run.startTime; | |
| 155 var x2 = run.startTime - run.duration; | |
| 156 | |
| 157 if (x1 > y2 && x2 < y1) { | |
| 158 var leftEdge = Math.min(x1, y1); | |
| 159 var rightEdge = Math.max(y2, x2); | |
| 160 | |
| 161 var dt = leftEdge - rightEdge; | |
| 162 | |
| 163 statusTotalsSeconds.Increment(run.entry.GetTreeState(), | |
| 164 DateUtil.MillisToSeconds(dt)); | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 return statusTotalsSeconds; | |
| 169 } | |
| 170 | |
| 171 function AddPeakColumn(tr, entries, utcDay, utcOffsetMillis, graphCSV) { | |
| 172 var td = DomUtil.AddNode(tr, "td"); | |
| 173 | |
| 174 // Width is (100/[items in utcMillisOffsets])%. | |
| 175 td.width = "25%"; | |
| 176 td.align = "center"; | |
| 177 | |
| 178 // Get a day range for the timezone. | |
| 179 var day = new TimeRange(utcDay.startTime - utcOffsetMillis, | |
| 180 utcDay.endTime - utcOffsetMillis); | |
| 181 | |
| 182 // Extract the data from |entries| that apply to |day|, and break it | |
| 183 // into (start,duration) runs. | |
| 184 var runs = MakeRuns(entries, day); | |
| 185 | |
| 186 // 9 - 5 in the local timezone. | |
| 187 var localPeakHours = new TimeRange( | |
| 188 day.endTime + 17 * DateUtil.MILLIS_PER_HOUR, | |
| 189 day.endTime + 9 * DateUtil.MILLIS_PER_HOUR); | |
| 190 | |
| 191 var statusTotalsSeconds = GetStateCountsInRange(runs, localPeakHours); | |
| 192 | |
| 193 var total = statusTotalsSeconds.GetTotalKnown(); | |
| 194 | |
| 195 var percentOpenText = ""; | |
| 196 var color = ""; | |
| 197 var className = ""; | |
| 198 | |
| 199 var percentOpenNumber = "0.0"; | |
| 200 if (total == 0) { | |
| 201 // This can happen if the day is in the future (edge day of slow timezone). | |
| 202 percentOpenText = "N/A"; | |
| 203 } else { | |
| 204 var fraction = statusTotalsSeconds.GetOpen() / total; | |
| 205 percentOpenNumber = (100 * fraction).toFixed(2); | |
| 206 percentOpenText = percentOpenNumber + "%"; | |
| 207 | |
| 208 // If we didn't fetch all the data necessary, our percentage won't be | |
| 209 // accurate as it is missing zones. | |
| 210 if (total != DateUtil.MillisToSeconds( | |
| 211 localPeakHours.startTime - localPeakHours.endTime)) { | |
| 212 percentOpenText += " [incomplete]"; | |
| 213 } | |
| 214 | |
| 215 // Choose a style based on how bad things are. | |
| 216 var badnessBuckets = [0.50, 0.75, 1.1]; | |
| 217 for (var i = 0; i < badnessBuckets.length; ++i) { | |
| 218 if (fraction < badnessBuckets[i]) { | |
| 219 className = "open_badness" + i; | |
| 220 break; | |
| 221 } | |
| 222 } | |
| 223 } | |
| 224 graphCSV.push("," + percentOpenNumber); | |
| 225 | |
| 226 var span = DomUtil.AddNode(td, "span"); | |
| 227 span.className = className; | |
| 228 DomUtil.AddText(span, percentOpenText); | |
| 229 } | |
| 230 | |
| 231 /** | |
| 232 * Draws a specific day's name column in the peak hours charts. | |
| 233 * @param {TimeRange} utcDay | |
| 234 * @param {DOMNode} td The column to print name into. | |
| 235 */ | |
| 236 function DrawUTCDayNameColumn(utcDay, td) { | |
| 237 var d = new Date(); | |
| 238 d.setTime(utcDay.endTime); | |
| 239 | |
| 240 // Display the day as for example "2009/8/38". | |
| 241 var dateText = | |
| 242 d.getUTCFullYear() + "/" + | |
| 243 PadWithZero(d.getUTCMonth() + 1, 2) + "/" + | |
| 244 PadWithZero(d.getUTCDate(), 2); | |
| 245 | |
| 246 // Color saturday and sunday differently. | |
| 247 if (d.getUTCDay() == 0) { | |
| 248 td.className = "sundayName"; | |
| 249 } else if (d.getUTCDay() == 6) { | |
| 250 td.className = "saturdayName"; | |
| 251 } | |
| 252 | |
| 253 td.innerHTML = dateText; | |
| 254 } | |
| 255 | |
| 256 })(); // Private implementation. | |
| OLD | NEW |