Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HiveStatistics/sources/HeuristicLab.Services.Hive.Statistics/3.3/App_Code/ChartHelper.cshtml @ 11084

Last change on this file since 11084 was 11084, checked in by mroscoe, 10 years ago
File size: 22.3 KB
Line 
1@* HeuristicLab
2 * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
3 *
4 * This file is part of HeuristicLab.
5 *
6 * HeuristicLab is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * HeuristicLab is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
18 *@
19
20@helper AjaxDataRenderer()
21{
22    <script>
23        var ajaxDataRenderer = function (url, plot, options) {
24            var ret = null;
25            $.ajax({
26                async: false,
27                url: url,
28                dataType: "json",
29                success: function (data) {
30                    ret = data;
31                }
32            });
33            return ret;
34        };
35    </script>
36}
37
38@helper LineChartTime(string destinationTag, string url, string title = "", double? minY = null, double? maxY = null, string axisYFormat = null)
39{
40    <script>
41        var @(destinationTag)Plot = $.jqplot("@destinationTag", "@url", {
42            title: "@title",
43            highlighter: {
44                show: true,
45                sizeAdjust: 7.5
46            },
47            seriesDefaults: {
48                markerOptions: { show: false }
49            },
50            dataRenderer: ajaxDataRenderer,
51            axes: {
52                xaxis: {
53                    renderer: $.jqplot.DateAxisRenderer,
54                    pad: 0
55                },
56                yaxis: {
57                    @if (axisYFormat != null)
58                    {<text>
59                    tickOptions: {
60                        formatString: "@axisYFormat",
61                    },
62                    </text>}
63                    autoscale: true,
64                    pad: 0,
65                    @if (minY != null)
66                    {
67                        @:min: @minY,
68                    }
69                    @if (maxY != null)
70                    {
71                        @:max: @maxY,
72                    }
73                },
74            },
75            gridPadding: { left: 50, right: 10 },
76            cursor: {
77                show: true,
78                showTooltip: false,
79                zoom: true,
80                clickReset: false,
81                dblClickReset: false,
82                constrainZoomTo: 'x'
83            }
84        });
85       
86        $(window).resize(function() {
87            @(destinationTag)Plot.replot({ resetAxes: true });
88        });
89    </script>
90}
91
92@helper RefreshChart(string destinationTag, string url, string startDate, string endDate)
93{
94  <text>
95  $.ajax({url: "@(new HtmlString(url))?start=" + @startDate + "&end=" + @endDate, datatype: "json", success: function(result) {
96    for (var i = 0; i < result.length; i++) {
97      @(destinationTag)Plot.series[i].data = result[i];
98    }
99    @(destinationTag)Plot.replot({ resetAxes: true })
100  }});
101  </text>
102}
103
104@helper ResizeCharts()
105{
106  <text>
107  function resizeCharts(caller) {
108    //If current plot is collapsed
109    if($(caller).css("display") == "none") {
110      //Display the contents of chartContainer
111      ResizeOpenClose($(caller).siblings(".collapse"));
112      //Reset barWidth for bar charts
113      $.each(window[caller.id].series, function(index, series) {
114        series.barWidth = undefined;
115      });
116      //Replot the chart with same name as element id
117      window[caller.id].replot({ resetAxes: false });
118      //Hide the contents of the current div
119      ResizeOpenClose($(caller).siblings(".collapse"));
120    }
121    //Current plot is expanded
122    else {
123      //Reset barWidth for bar charts
124      $.each(window[caller.id].series, function(index, series) {
125        series.barWidth = undefined;
126      });
127      //Replot the chart with same name as element id
128      window[caller.id].replot({ resetAxes: false });
129    }
130  }
131
132  $(window).resize(function() {
133    $("div.jqplot-target",".chartContainer").each(function() {
134      var potentialTab = $(this).parent().parent().parent();
135      //If the section is tabular and currently hidden
136      if(potentialTab.hasClass("tabSection") && potentialTab.css("display") == "none") {
137        ResizeOpenCloseTabular(potentialTab);
138        resizeCharts(this);
139        ResizeOpenCloseTabular(potentialTab);
140      }
141      else {
142        resizeCharts(this);
143      }
144    });
145  });
146  </text>
147}
148
149@helper NumberPages(string records, string limit, string container, string functionName, string currentPage = null)
150{
151  <text>
152    if(@(records).length > @limit) {
153      $("#@container").append('<label class="pageTitle">Page: </label>')
154      var pages = Math.floor(@(records).length/@(limit)) + 1;
155      for(var i=0; i < pages; i++) {
156        $("#" + "@container").append('<a id="@(container)Page' + (i + 1) + '" class="page">' + (i + 1) + '</a>')
157      }
158      if(@currentPage != null) {
159        $("#@(container)Page" + @currentPage).css('color','#F7921D');
160      }
161      else {
162        $("#@(container)Page1").css('color','#F7921D');
163      }
164      $(".page").click(function () {
165        pageNumber = $(this).html();
166        @(functionName)();
167      });
168      if(@currentPage != null) {
169        @(records).splice(0,(@(currentPage)-1)*@(limit));
170        if (@(records).length > @(limit)) {
171          @(records).splice(@(limit), @(records).length - @(limit));
172        }
173      }
174      else {
175        @(records).splice(@(limit), @(records).length - @(limit));
176      }
177    }
178  </text>
179}
180
181@helper TasksForUser(string destinationTag, string url, string functionName, string userName, string limit, string startDate = null, string endDate = null, string jobId = null, string taskState = null, string pageNumber = null)
182{
183  <text>
184    var GetRequest = "?userName=" + @(userName);
185    @if (startDate != null)
186    {
187      @:if(@(startDate)!=null) {
188        @:GetRequest += "&start=" + @startDate;
189      @:}
190    }
191    @if (endDate != null)
192    {
193      @:if(@(endDate)!=null) {
194        @:GetRequest += "&end=" + @endDate;
195      @:}
196    }
197    @if (jobId != null)
198    {
199      @:if(@(jobId)!=null) {
200        @:GetRequest += "&jobId=" + @jobId;
201      @:}
202    }
203    @if (taskState != null)
204    {
205      @:if(@(taskState)!=null) {
206        @:GetRequest += "&taskState=" + @taskState;
207      @:}
208    }
209    $.ajax({
210      async: false, url: "@(new HtmlString(url))" + GetRequest, datatype: "json", success: function(result) {
211      if(@(userName) == null) {
212        $("#@(destinationTag)").append(
213          '<section class="chartContainer">' +
214            '<h1 class="title">Please select a user!</h1>' +
215          '</section>'
216        )
217      }
218      else if(result.length==0) {
219        $("#@(destinationTag)").append(
220          '<section class="chartContainer">' +
221            '<h1 class="title">' + @userName + ' has no tasks for the specified filters!</h1>' +
222          '</section>'
223        )
224      }
225      else {
226        var waitTime;
227        var transferTime;
228        var runTime;
229        var seriesDescriptions = ["Time waiting","Time transferring","Time calculating"];
230
231        //Checks if multipage display, if it is then trims results to
232        //the results for the page to be displayed
233        @ChartHelper.NumberPages("result", limit, destinationTag, functionName, pageNumber)
234
235        //Globally accesible, for use when resizing, eliminates extra DB request
236        window["numberTasks"] = result.length;
237
238        //Set display of all errors to none, errors matching the tasks will be reset below
239        $("#@(destinationTag)").find(".errorContainer, .errorTitle, .errorTask, .errorMessage").css('display','none');
240
241        //For each result create a seperate collapsable section with a chart and info label
242        for(var i = 0; i < result.length; i++){
243          $("#" + "@(destinationTag)").append(
244            '<section class="chartContainer">' +
245              '<h1 class="title" id="@(destinationTag)' + result[i].Key + 'PlotTitle">Task ' + result[i].Key + '</h1>' +
246              '<button class="collapse" onclick="CollapseSection(this)">+</button>' +
247              '<div id="@(destinationTag)Plot' + i + '"></div>' +
248              '<label id="@(destinationTag)PlotInfo' + i + '"></label>' +
249            '</section>'
250          )
251          //Re-enables the error display if any of the tasks on the page have Ids matching
252          //those of errors
253          $(".errorTask","#" + "@(destinationTag)").each(function() {
254            if($(this).html()==result[i].Key) {
255              $("#@(destinationTag)" + result[i].Key + "PlotTitle").css("color","red");
256              $("#@(destinationTag)" + result[i].Key + "PlotTitle").append(" - ERROR");
257              $(".errorContainer, .errorTitle, .underline","#@(destinationTag)").css('display','inline-block');
258              $(this).css('display','inline-block');
259              $(this).next().css('display','inline-block');
260            }
261          });
262          waitTime = [result[i].Value[0]];
263          transferTime = [result[i].Value[1]];
264          runTime = [result[i].Value[2]];
265          window["@(destinationTag)Plot" + i] = $.jqplot("@(destinationTag)Plot" + i, [waitTime,transferTime,runTime], {
266            seriesDefaults:{
267              renderer:$.jqplot.BarRenderer,
268              shadowAngle: 135,
269              pointLabels: {show: true, formatString: '%.3f'}
270            },
271            series:[
272              {label:'Waiting'},
273              {label:'Transferring'},
274              {label:'Calculating'}
275            ],
276            legend: {
277              show: true,
278              location: 'e',
279              placement: 'outside'
280            },
281            axes: {
282              xaxis: {
283                renderer: $.jqplot.CategoryAxisRenderer,
284                showLabel: false,
285                pad: 0
286              },
287              yaxis: {
288                pad: 0
289              }
290            },
291            cursor: {
292              showTooltip: false
293            }
294          });
295          /* Bind a datalistener to each chart and display details of clicked
296            upon data in the label below the chart */
297          $("#" + "@(destinationTag)Plot" + i).bind('jqplotDataClick', function (ev, seriesIndex, pointIndex, data) {
298            $(this).siblings("label").html(seriesDescriptions[seriesIndex] + ": " + data[1]);
299          });
300
301          CollapsedByDefault(document.getElementById("@(destinationTag)Plot" + i));
302        }
303      }
304    }});
305  </text>
306}
307
308@helper SetStreamingProperties(int refresh, int chartLength, int upperY)
309{
310  <text>
311  //Refresh time (in millisec)
312  var refreshRate = @(refresh);
313  //Number of data points on chart
314  var chartSize = @(chartLength);
315  //Amount to add to max Y value
316  var upperYBuffer = @(upperY);
317
318  //Used to return a string containing the names of the series
319  //to be used in plot creation
320  function GetSeries(numberData,dataName){
321    var result = "[";
322    for(i=0; i < numberData; i++) {
323      if(i < numberData -1) {
324        result += dataName + i + ",";
325      }
326      else {
327        result += dataName + i + "]";
328      }
329    }
330    return result;
331  }
332  </text>
333}
334
335@helper CreateStreamChart(string dataName, string destinationTag, string url, string title, string format = null, double? maxY = null)
336{
337  <text>
338  //Get current time, used to create initial values
339  var @(dataName)CurrentDate = (new Date()).getTime();
340
341  var @(dataName)Data = [];
342  var @(dataName)CurrentValue = [];
343
344  //Get the most recent value(s) from the given URL
345  $.ajax({
346    async: false, url: '@(url)', datatype: "json", success: function (result) {
347      for(i = 0; i < result.length; i++) {
348        @(dataName)CurrentValue[i] = result[i];
349      }
350    }
351  });
352 
353  //Create a chartSize worth of data using CurrentDate and CurrentValue
354  //for each CurrentValue
355  for(i = 0; i < @(dataName)CurrentValue.length; i++) {
356    window["@(dataName)Data" + i] = [];
357    for (j = 0; j < chartSize; j++) {
358      window[ "@(dataName)Data" + i].push([@(dataName)CurrentDate - (chartSize - 1 - j) * refreshRate, @(dataName)CurrentValue[i]]);
359    }
360  }
361
362  //Options for the chart to be created
363  var @(destinationTag)PlotOptions = {
364    title: "@title",
365    axes: {
366      xaxis: {
367        numberTicks: 4,
368        renderer: $.jqplot.DateAxisRenderer,
369        tickOptions: { formatString: '%H:%M:%S' },
370        min: window["@(dataName)Data" + 0][0][0],
371        max: window["@(dataName)Data" + 0][window["@(dataName)Data" + 0].length - 1][0]
372      },
373      yaxis: {
374        @if (format != null)
375        {<text>
376        tickOptions: {
377            formatString: "@format",
378        },
379        </text>}
380        min: 0,
381        @if (maxY != null)
382        {
383          @:max: @maxY,
384        }
385        else
386        {
387          @:max: window["@(dataName)Data" + 0][window["@(dataName)Data" + 0].length - 1][1] + upperYBuffer,
388        }
389        numberTicks: 6
390      }
391    },
392    seriesDefaults: {
393      rendererOptions: { smooth: true },
394      markerOptions: {
395        show: false
396      }
397    }
398  };
399
400  //Declares the jqPlot variable, evals the string of series returned
401  //from getSeries which allows for any number of series
402  window[ "@(destinationTag)Plot"] = $.jqplot('@destinationTag', eval(GetSeries(@(dataName)CurrentValue.length,"@(dataName)Data")), @(destinationTag)PlotOptions);
403  </text>
404}
405
406@helper UpdateStreamChart(string dataName, string destinationTag, string url, string fixedY = null)
407{
408  <text>
409  //If the data is beyond chartSize use shift to trim one off the end
410  for(i = 0; i < @(dataName)CurrentValue.length; i++) {
411    if (window["@(dataName)Data" + i].length > chartSize - 1) {
412      window["@(dataName)Data" + i].shift();
413    }
414  }
415
416  //Get the up-to-date data, each result assigned to it's own array
417  $.ajax({
418    async: false, url: '@(url)', datatype: "json", success: function (result) {
419      for(i = 0; i < result.length; i++) {
420        window[ "@(dataName)Data" + i].push([(new Date()).getTime(), result[i]]);
421      }
422    }
423  });
424
425  //If the plot exists currently destroy it
426  if ( @(destinationTag)Plot) {
427    @(destinationTag)Plot.destroy();
428  }
429
430  //Assign series
431  for(i = 0; i < @(dataName)CurrentValue.length; i++) {
432    @(destinationTag)Plot.series[i].data = window["@(dataName)Data" + i];
433  }
434
435  //Recalculate x and possibly y axis max and mins
436  @(destinationTag)PlotOptions.axes.xaxis.min = window["@(dataName)Data" + 0][0][0];
437  @(destinationTag)PlotOptions.axes.xaxis.max = window["@(dataName)Data" + 0][window["@(dataName)Data" + 0].length - 1][0];
438  @if (fixedY == null)
439  {
440    @:@(destinationTag)PlotOptions.axes.yaxis.max = window["@(dataName)Data" + 0][window["@(dataName)Data" + 0].length - 1][1] + upperYBuffer;
441  }
442
443  //Re-assigns the jqPlot variable, evals the string of series returned
444  //from getSeries which allows for any number of series
445  @(destinationTag)Plot = $.jqplot('@destinationTag', eval(GetSeries(@(dataName)CurrentValue.length,"@(dataName)Data")), @(destinationTag)PlotOptions);
446  </text>
447}
448
449@helper SlaveInfoChart(string destinationTag, string url, string limit, bool singleSlave, string startDate = null, string endDate = null, string userName = null, string functionName = null, string pageNumber = null, string slaveId = null)
450{
451  <text>
452  var GetRequest = "";
453  @if (startDate != null)
454  {
455    @:if(@(startDate)!=null) {
456      @:if(GetRequest == "") {
457        @:GetRequest += "?start=" + @startDate;
458      @:}
459      @:else {
460        @:GetRequest += "&start=" + @startDate;
461      @:}
462    @:}
463  }
464  @if (endDate != null)
465  {
466    @:if(@(endDate)!=null) {
467      @:if(GetRequest == "") {
468        @:GetRequest += "?end=" + @endDate;
469      @:}
470      @:else {
471        @:GetRequest += "&end=" + @endDate;
472      @:}
473    @:}
474  }
475  @if (userName != null)
476  {
477    @:if(@(userName)!=null) {
478      @:if(GetRequest == "") {
479        @:GetRequest += "?userName=" + @userName;
480      @:}
481      @:else {
482        @:GetRequest += "&userName=" + @userName;
483      @:}
484    @:}
485  }
486  @if (slaveId != null)
487  {
488    @:if(@(slaveId)!=null) {
489      @:if(GetRequest == "") {
490        @:GetRequest += "?slaveId=" + @slaveId;
491      @:}
492      @:else {
493        @:GetRequest += "&slaveId=" + @slaveId;
494      @:}
495    @:}
496  }
497  $.ajax({
498    async: false, url: "@(new HtmlString(url))" + GetRequest, datatype: "json", success: function(result) {
499
500    //Set chart names for use in creation below, must be set identically in
501    //ResizeSlaves
502    var slaveChartNames = ["TotalUsedCores","TotalUsedMemory","CPUUtilization"];
503
504    var destTag = eval("@(destinationTag)");
505    if(typeof eval("@(destinationTag)") != "string") {
506      destTag = "@(destinationTag)";
507    }
508
509    if(result.length == 0) {
510      @if (!singleSlave) {
511        @:$('#' + destTag).html("");
512      }
513      $('#' + destTag).append(
514        '<section class="chartContainer">' +
515          '<h1 class="title">No slave information for the specified filters!</h1>' +
516        '</section>'
517      )
518    }
519    else {
520      var time = new Date();
521
522      @if (!singleSlave)
523      {
524        @:$('#' + destTag).html("");
525
526        //Checks if multipage display, if it is then trims results to
527        //the results for the page to be displayed
528        @ChartHelper.NumberPages("result", limit, destinationTag, functionName, pageNumber)
529      }
530
531      for(i = 0; i < result.length; i++) {
532        var coreSeries = [];
533        coreSeries[0] = [];
534        coreSeries[1] = [];
535        var memorySeries = [];
536        memorySeries[0] = [];
537        memorySeries[1] = [];
538        var cpuSeries = [];
539        cpuSeries[0] = [];
540        $('#' + destTag).append(
541          '<section class="chartContainer">' +
542            '<h1 class="title" id="' + destTag + result[i][0].SlaveID + 'PlotTitle">Slave ' + result[i][0].SlaveID + '</h1>' +
543            '<button class="collapse" onclick="CollapseSection(this)">+</button>' +
544            '<div id="' + destTag + slaveChartNames[0] + 'Plot' + i + '"></div>' +
545            '<div id="' + destTag + slaveChartNames[1] + 'Plot' + i + '"></div>' +
546            '<div id="' + destTag + slaveChartNames[2] + 'Plot' + i + '"></div>' +
547          '</section>');
548        for(j = 0; j < result[i].length; j++) {
549          time.setTime(result[i][j].Time.replace(/\D/g,''));
550          coreSeries[0].push([time.toUTCString(),result[i][j].TotalCores]);
551          coreSeries[1].push([time.toUTCString(),result[i][j].UsedCores]);
552          memorySeries[0].push([time.toUTCString(),(result[i][j].TotalMemory / 1000)]);
553          memorySeries[1].push([time.toUTCString(),(result[i][j].UsedMemory / 1000)]);
554          cpuSeries[0].push([time.toUTCString(),result[i][j].CPUUtilization]);
555        }
556        if(result[i].length > 1) {
557          @ChartHelper.LineChartGivenSeries("destTag + slaveChartNames[0]", "i", "coreSeries", "Total/Used Cores")
558          @ChartHelper.LineChartGivenSeries("destTag + slaveChartNames[1]", "i", "memorySeries", "Total/Used Memory", 0)
559          @ChartHelper.LineChartGivenSeries("destTag + slaveChartNames[2]", "i", "cpuSeries", "CPU Utilization", 0, 100, "%.1f%%")
560        }
561        else {
562          @ChartHelper.BarChartGivenSeries("destTag + slaveChartNames[0]", "i", "coreSeries", "Total/Used Cores")
563          @ChartHelper.BarChartGivenSeries("destTag + slaveChartNames[1]", "i", "memorySeries", "Total/Used Memory", 0)
564          @ChartHelper.BarChartGivenSeries("destTag + slaveChartNames[2]", "i", "cpuSeries", "CPU Utilization", 0, 100, "%.1f%%")
565        }
566        for(k = 0; k < slaveChartNames.length; k++) {
567          CollapsedByDefault(document.getElementById(destTag + slaveChartNames[k] + "Plot" + i));
568        }
569      }
570    }
571  }});
572  </text>
573}
574
575@helper LineChartGivenSeries(string destinationTag, string chartId, string series, string title, double? minY = null, double? maxY = null, string axisYFormat = null)
576{
577  <text>
578  window[@(destinationTag) + "Plot" + @(chartId)] = $.jqplot(@(destinationTag) + "Plot" + @(chartId), @series, {
579    title: "@title",
580    axes: {
581      xaxis: {
582        renderer: $.jqplot.DateAxisRenderer,
583        tickOptions:{formatString:'%b %#d, %y'},
584        pad: 0
585      },
586      yaxis: {
587        @if (axisYFormat != null)
588        {
589          <text>
590          tickOptions: {
591              formatString: "@axisYFormat"
592          },
593          </text>
594        }
595        pad: 0,
596        @if (minY != null)
597        {
598            @:min: @minY,
599        }
600        @if (maxY != null)
601        {
602            @:max: @maxY,
603        }
604      }
605    },
606    gridPadding: { left: 50, right: 10 },
607    cursor: {
608      show: true,
609      showTooltip: false,
610      zoom: true,
611      clickReset: false,
612      dblClickReset: false,
613      constrainZoomTo: 'x'
614    }
615  });
616  </text>
617}
618
619@helper BarChartGivenSeries(string destinationTag, string chartId, string series, string title, double? minY = null, double? maxY = null, string axisYFormat = null)
620{
621  <text>
622  window[@(destinationTag) + "Plot" + @(chartId)] = $.jqplot(@(destinationTag) + "Plot" + @(chartId), @series, {
623    title: "@title",
624    seriesDefaults:{
625      renderer:$.jqplot.BarRenderer,
626      shadowAngle: 135,
627      pointLabels: {show: true, formatString: '%.2f'}
628    },
629    axes: {
630      xaxis: {
631        renderer: $.jqplot.CategoryAxisRenderer,
632        tickOptions:{formatString:'%b %#d, %y'},
633        pad: 0
634      },
635      yaxis: {
636        @if (axisYFormat != null)
637        {
638          <text>
639          tickOptions: {
640              formatString: "@axisYFormat"
641          },
642          </text>
643        }
644        pad: 0,
645        @if (minY != null)
646        {
647            @:min: @minY,
648        }
649        @if (maxY != null)
650        {
651            @:max: @maxY,
652        }
653      }
654    },
655    gridPadding: { left: 50, right: 10 },
656    cursor: {
657      show: true,
658      showTooltip: false,
659      zoom: true,
660      clickReset: false,
661      dblClickReset: false,
662      constrainZoomTo: 'x'
663    }
664  });
665  </text>
666}
Note: See TracBrowser for help on using the repository browser.