Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 11053 was 11053, checked in by mroscoe, 10 years ago
File size: 21.0 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 NumberPages(string records, string limit, string container, string functionName, string currentPage = null)
105{
106  <text>
107    if(@(records).length > @limit) {
108      $("#@container").append('<label class="pageTitle">Page: </label>')
109      var pages = Math.floor(@(records).length/@(limit)) + 1;
110      for(var i=0; i < pages; i++) {
111        $("#" + "@container").append('<a id="@(container)Page' + (i + 1) + '" class="page">' + (i + 1) + '</a>')
112      }
113      if(@currentPage != null) {
114        $("#@(container)Page" + @currentPage).css('color','#F7921D');
115      }
116      else {
117        $("#@(container)Page1").css('color','#F7921D');
118      }
119      $(".page").click(function () {
120        pageNumber = $(this).html();
121        @(functionName)();
122      });
123      if(@currentPage != null) {
124        @(records).splice(0,(@(currentPage)-1)*@(limit));
125        if (@(records).length > @(limit)) {
126          @(records).splice(@(limit), @(records).length - @(limit));
127        }
128      }
129      else {
130        @(records).splice(@(limit), @(records).length - @(limit));
131      }
132    }
133  </text>
134}
135
136@helper TasksForUser(string container, 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)
137{
138  <text>
139    var GetRequest = "?userName=" + @(userName) + "&limit=" + @(limit);
140    @if(startDate!=null) {
141      @:if(@(startDate)!=null) {
142        @:GetRequest += "&start=" + @startDate;
143      @:}
144    }
145    @if(endDate!=null) {
146      @:if(@(endDate)!=null) {
147        @:GetRequest += "&end=" + @endDate;
148      @:}
149    }
150    @if(jobId!=null) {
151      @:if(@(jobId)!=null) {
152        @:GetRequest += "&jobId=" + @jobId;
153      @:}
154    }
155    @if(taskState!=null) {
156      @:if(@(taskState)!=null) {
157        @:GetRequest += "&taskState=" + @taskState;
158      @:}
159    }
160    $.ajax({
161      async: false, url: "@(new HtmlString(url))" + GetRequest, datatype: "json", success: function(result) {
162      if(@(userName) == null) {
163        $("#@container").append(
164          '<section class="chartContainer">' +
165            '<h1 class="title">Please select a user!</h1>' +
166          '</section>'
167        )
168      }
169      else if(result.length==0) {
170        $("#@container").append(
171          '<section class="chartContainer">' +
172            '<h1 class="title">' + @userName + ' has no tasks for the specified filters!</h1>' +
173          '</section>'
174        )
175      }
176      else {
177        var waitTime;
178        var transferTime;
179        var runTime;
180        var seriesDescriptions = ["Time waiting","Time transferring","Time calculating"];
181
182        //Checks if multipage display, if it is then trims results to
183        //the results for the page to be displayed
184        @ChartHelper.NumberPages("result",limit,container,functionName,pageNumber)
185
186        //Globally accesible, for use when resizing, eliminates extra DB request
187        window["numberTasks"] = result.length;
188
189        //Set display of all errors to none, errors matching the tasks will be reset below
190        $("#@(container)").find(".errorContainer, .errorTitle, .errorTask, .errorMessage").css('display','none');
191
192        //For each result create a seperate collapsable section with a chart and info label
193        for(var i = 0; i < result.length; i++){
194          $("#" + "@container").append(
195            '<section class="chartContainer">' +
196              '<h1 class="title" id="@(container)' + result[i].Key + '">Task ' + result[i].Key + '</h1>' +
197              '<button class="collapse" onclick="CollapseSection(this)">+</button>' +
198              '<div id="@(destinationTag)Plot' + i + '"></div>' +
199              '<label id="@(destinationTag)PlotInfo' + i + '"></label>' +
200            '</section>'
201          )
202          //Re-enables the error display if any of the tasks on the page have Ids matching
203          //those of errors
204          $(".errorTask").each(function() {
205            if($(this).html()==result[i].Key) {
206              $("#@(container)" + result[i].Key).css("color","red");
207              $("#@(container)" + result[i].Key).append(" - ERROR");
208              $(".errorContainer, .errorTitle, .underline").css('display','inline-block');
209              $(this).css('display','inline-block');
210              $(this).next().css('display','inline-block');
211            }
212          });
213          waitTime = [result[i].Value[0]];
214          transferTime = [result[i].Value[1]];
215          runTime = [result[i].Value[2]];
216          window["@(destinationTag)Plot" + i] = $.jqplot("@(destinationTag)Plot" + i, [waitTime,transferTime,runTime], {
217            seriesDefaults:{
218              renderer:$.jqplot.BarRenderer,
219              shadowAngle: 135,
220              pointLabels: {show: true, formatString: '%.3f'}
221            },
222            series:[
223              {label:'Waiting'},
224              {label:'Transferring'},
225              {label:'Calculating'}
226            ],
227            legend: {
228              show: true,
229              location: 'e',
230              placement: 'outside'
231            },
232            axes: {
233              xaxis: {
234                renderer: $.jqplot.CategoryAxisRenderer,
235                showLabel: false,
236                pad: 0
237              },
238              yaxis: {
239                pad: 0
240              }
241            },
242            cursor: {
243              showTooltip: false
244            }
245          });
246          /* Bind a datalistener to each chart and display details of clicked
247            upon data in the label below the chart */
248          $("#" + "@(destinationTag)Plot" + i).bind('jqplotDataClick', function (ev, seriesIndex, pointIndex, data) {
249            $(this).siblings("label").html(seriesDescriptions[seriesIndex] + ": " + data[1]);
250          });
251
252          CollapsedByDefault(document.getElementById("@(container)" + result[i].Key));
253        }
254      }
255    }});
256  </text>
257}
258
259@helper ResizeTasks(string destinationTag)
260{
261  <text>
262  //Resize event, resets bar width for task charts and replots them
263  $(window).resize(function() {
264    if(typeof numberTasks !== 'undefined') {
265      for(var i = 0; i < numberTasks; i++) {
266        $.each(window[ "@(destinationTag)Plot" + i].series, function(index, series) {
267          series.barWidth = undefined;
268        });
269        window["@(destinationTag)Plot" + i].replot({ resetAxes: true });
270      }
271    }
272  });
273  </text>
274}
275
276@helper SetStreamingProperties(int refresh, int chartLength, int upperY) {
277  <text>
278  //Refresh time (in millisec)
279  var refreshRate = @(refresh);
280  //Number of data points on chart
281  var chartSize = @(chartLength);
282  //Amount to add to max Y value
283  var upperYBuffer = @(upperY);
284
285  //Used to return a string containing the names of the series
286  //to be used in plot creation
287  function GetSeries(numberData,dataName){
288    var result = "[";
289    for(i=0; i < numberData; i++) {
290      if(i < numberData -1) {
291        result += dataName + i + ",";
292      }
293      else {
294        result += dataName + i + "]";
295      }
296    }
297    return result;
298  }
299  </text>
300}
301
302@helper CreateStreamChart(string dataName, string destinationTag, string url, string title, string format = null, double? maxY = null) {
303  <text>
304  //Get current time, used to create initial values
305  var @(dataName)CurrentDate = (new Date()).getTime();
306
307  var @(dataName)Data = [];
308  var @(dataName)CurrentValue = [];
309
310  //Get the most recent value(s) from the given URL
311  $.ajax({
312    async: false, url: '@(url)', datatype: "json", success: function (result) {
313      for(i = 0; i < result.length; i++) {
314        @(dataName)CurrentValue[i] = result[i];
315      }
316    }
317  });
318 
319  //Create a chartSize worth of data using CurrentDate and CurrentValue
320  //for each CurrentValue
321  for(i = 0; i < @(dataName)CurrentValue.length; i++) {
322    window["@(dataName)Data" + i] = [];
323    for (j = 0; j < chartSize; j++) {
324      window[ "@(dataName)Data" + i].push([@(dataName)CurrentDate - (chartSize - 1 - j) * refreshRate, @(dataName)CurrentValue[i]]);
325    }
326  }
327
328  //Options for the chart to be created
329  var @(destinationTag)PlotOptions = {
330    title: "@title",
331    axes: {
332      xaxis: {
333        numberTicks: 4,
334        renderer: $.jqplot.DateAxisRenderer,
335        tickOptions: { formatString: '%H:%M:%S' },
336        min: window["@(dataName)Data" + 0][0][0],
337        max: window["@(dataName)Data" + 0][window["@(dataName)Data" + 0].length - 1][0]
338      },
339      yaxis: {
340        @if (format != null)
341        {<text>
342        tickOptions: {
343            formatString: "@format",
344        },
345        </text>}
346        min: 0,
347        @if (maxY != null) {
348          @:max: @maxY,
349        }
350        else{
351          @:max: window["@(dataName)Data" + 0][window["@(dataName)Data" + 0].length - 1][1] + upperYBuffer,
352        }
353        numberTicks: 6
354      }
355    },
356    seriesDefaults: {
357      rendererOptions: { smooth: true },
358      markerOptions: {
359        show: false
360      }
361    }
362  };
363
364  //Declares the jqPlot variable, evals the string of series returned
365  //from getSeries which allows for any number of series
366  window[ "@(destinationTag)Plot"] = $.jqplot('@destinationTag', eval(GetSeries(@(dataName)CurrentValue.length,"@(dataName)Data")), @(destinationTag)PlotOptions);
367  </text>
368}
369
370@helper UpdateStreamChart(string dataName, string destinationTag, string url, string fixedY = null) {
371  <text>
372  //If the data is beyond chartSize use shift to trim one off the end
373  for(i = 0; i < @(dataName)CurrentValue.length; i++) {
374    if (window["@(dataName)Data" + i].length > chartSize - 1) {
375      window["@(dataName)Data" + i].shift();
376    }
377  }
378
379  //Get the up-to-date data, each result assigned to it's own array
380  $.ajax({
381    async: false, url: '@(url)', datatype: "json", success: function (result) {
382      for(i = 0; i < result.length; i++) {
383        window[ "@(dataName)Data" + i].push([(new Date()).getTime(), result[i]]);
384      }
385    }
386  });
387
388  //If the plot exists currently destroy it
389  if ( @(destinationTag)Plot) {
390    @(destinationTag)Plot.destroy();
391  }
392
393  //Assign series
394  for(i = 0; i < @(dataName)CurrentValue.length; i++) {
395    @(destinationTag)Plot.series[i].data = window["@(dataName)Data" + i];
396  }
397
398  //Recalculate x and possibly y axis max and mins
399  @(destinationTag)PlotOptions.axes.xaxis.min = window["@(dataName)Data" + 0][0][0];
400  @(destinationTag)PlotOptions.axes.xaxis.max = window["@(dataName)Data" + 0][window["@(dataName)Data" + 0].length - 1][0];
401  @if (fixedY == null) {
402    @:@(destinationTag)PlotOptions.axes.yaxis.max = window["@(dataName)Data" + 0][window["@(dataName)Data" + 0].length - 1][1] + upperYBuffer;
403  }
404
405  //Re-assigns the jqPlot variable, evals the string of series returned
406  //from getSeries which allows for any number of series
407  @(destinationTag)Plot = $.jqplot('@destinationTag', eval(GetSeries(@(dataName)CurrentValue.length,"@(dataName)Data")), @(destinationTag)PlotOptions);
408  </text>
409}
410
411@helper SlaveInfoChart(string destinationTag, string url, string limit, string startDate, string endDate, string userName, string functionName, string pageNumber=null, string slaveId=null) {
412  <text>
413  var GetRequest = "?limit=" + @(limit);
414  @if(startDate!=null) {
415    @:if(@(startDate)!=null) {
416      @:GetRequest += "&start=" + @startDate;
417    @:}
418  }
419  @if(endDate!=null) {
420    @:if(@(endDate)!=null) {
421      @:GetRequest += "&end=" + @endDate;
422    @:}
423  }
424  @if (userName != null) {
425    @:if(@(userName)!=null) {
426      @:GetRequest += "&userName=" + @userName;
427    @:}
428  }
429  @if (slaveId != null) {
430    @:if(@(slaveId)!=null) {
431      @:GetRequest += "&slaveId=" + @slaveId;
432    @:}
433  }
434  $.ajax({
435    async: false, url: "@(new HtmlString(url))" + GetRequest, datatype: "json", success: function(result) {
436
437    //Set chart names for use in creation below, must be set identically in
438    //ResizeSlaves
439    var slaveChartNames = ["TotalUsedCores","TotalUsedMemory","CPUUtilization"];
440
441    if(result.length == 0) {
442      $('#' + "@(destinationTag)").append(
443        '<section class="chartContainer">' +
444          '<h1 class="title">No slave information for the specified filters!</h1>' +
445        '</section>'
446      )
447    }
448    else {
449      $('#' + "@(destinationTag)").html("");
450      var time = new Date();
451
452      //Checks if multipage display, if it is then trims results to
453      //the results for the page to be displayed
454      @ChartHelper.NumberPages("result",limit,destinationTag,functionName,pageNumber)
455
456      //Globally accesible, for use when resizing, eliminates extra DB request
457      window["numberSlaves"] = result.length;
458
459      for(i = 0; i < result.length; i++) {
460        var coreSeries = [];
461        coreSeries[0] = [];
462        coreSeries[1] = [];
463        var memorySeries = [];
464        memorySeries[0] = [];
465        memorySeries[1] = [];
466        var cpuSeries = [];
467        cpuSeries[0] = [];
468        $('#' + "@(destinationTag)").append(
469          '<section class="chartContainer">' +
470            '<h1 class="title" id="' + result[i][0].SlaveID + '">Slave ' + result[i][0].SlaveID + '</h1>' +
471            '<button class="collapse" onclick="CollapseSection(this)">+</button>' +
472            '<div id="' + slaveChartNames[0] + i + '"></div>' +
473            '<div id="' + slaveChartNames[1] + i + '"></div>' +
474            '<div id="' + slaveChartNames[2] + i + '"></div>' +
475          '</section>');
476        for(j = 0; j < result[i].length; j++) {
477          time.setTime(result[i][j].Time.replace(/\D/g,''));
478          coreSeries[0].push([time.toUTCString(),result[i][j].TotalCores]);
479          coreSeries[1].push([time.toUTCString(),result[i][j].UsedCores]);
480          memorySeries[0].push([time.toUTCString(),(result[i][j].TotalMemory / 1000)]);
481          memorySeries[1].push([time.toUTCString(),(result[i][j].UsedMemory / 1000)]);
482          cpuSeries[0].push([time.toUTCString(),result[i][j].CPUUtilization]);
483        }
484        if(result[i].length > 1) {
485          @ChartHelper.LineChartGivenSeries("slaveChartNames[0]","i","coreSeries","Total/Used Cores")
486          @ChartHelper.LineChartGivenSeries("slaveChartNames[1]","i","memorySeries","Total/Used Memory",0)
487          @ChartHelper.LineChartGivenSeries("slaveChartNames[2]","i","cpuSeries","CPU Utilization",0,100,"%.1f%%")
488        }
489        else {
490          @ChartHelper.BarChartGivenSeries("slaveChartNames[0]","i","coreSeries","Total/Used Cores")
491          @ChartHelper.BarChartGivenSeries("slaveChartNames[1]","i","memorySeries","Total/Used Memory",0)
492          @ChartHelper.BarChartGivenSeries("slaveChartNames[2]","i","cpuSeries","CPU Utilization",0,100,"%.1f%%")
493        }
494        for(k = 0; k < slaveChartNames.length; k++) {
495          CollapsedByDefault(document.getElementById(slaveChartNames[k] + i));
496        }
497      }
498    }
499  }});
500  </text>
501}
502
503@helper ResizeSlaves() {
504  <text>
505  //Resize event, resets bar width for slave charts and replots them
506  $(window).resize(function() {
507    if(typeof numberSlaves !== 'undefined') {
508
509    //Set chart names for use in creation below, must be set identically in
510    //ResizeSlaves
511    var slaveChartNames = ["TotalUsedCores","TotalUsedMemory","CPUUtilization"];
512
513      for(i = 0; i < numberSlaves; i++) {
514        for(j = 0; j < slaveChartNames.length; j++) {
515          $.each(window[slaveChartNames[j] + "Plot" + i].series, function(index, series) {
516            series.barWidth = undefined;
517          });
518          window[slaveChartNames[j] + "Plot" + i].replot({ resetAxes: true });
519        }
520      }
521    }
522  });
523  </text>
524}
525
526@helper LineChartGivenSeries(string destinationTag, string chartId, string series, string title, double? minY = null, double? maxY = null, string axisYFormat = null) {
527  <text>
528  window[@(destinationTag) + "Plot" + @(chartId)] = $.jqplot(@(destinationTag) + @(chartId), @series, {
529    title: "@title",
530    axes: {
531      xaxis: {
532        renderer: $.jqplot.DateAxisRenderer,
533        tickOptions:{formatString:'%b %#d, %y'},
534        pad: 0
535      },
536      yaxis: {
537        @if (axisYFormat != null) {
538          <text>
539          tickOptions: {
540              formatString: "@axisYFormat"
541          },
542          </text>
543        }
544        @if (minY != null) {
545            @:min: @minY,
546        }
547        @if (maxY != null) {
548            @:max: @maxY,
549        }
550        pad: 0
551      }
552    },
553    gridPadding: { left: 50, right: 10 },
554    cursor: {
555      show: true,
556      showTooltip: false,
557      zoom: true,
558      clickReset: false,
559      dblClickReset: false,
560      constrainZoomTo: 'x'
561    }
562  });
563  </text>
564}
565
566@helper BarChartGivenSeries(string destinationTag, string chartId, string series, string title, double? minY = null, double? maxY = null, string axisYFormat = null) {
567  <text>
568  window[@(destinationTag) + "Plot" + @(chartId)] = $.jqplot(@(destinationTag) + @(chartId), @series, {
569    title: "@title",
570    seriesDefaults:{
571      renderer:$.jqplot.BarRenderer,
572      shadowAngle: 135,
573      pointLabels: {show: true, formatString: '%.2f'}
574    },
575    axes: {
576      xaxis: {
577        renderer: $.jqplot.CategoryAxisRenderer,
578        tickOptions:{formatString:'%b %#d, %y'},
579        pad: 0
580      },
581      yaxis: {
582        @if (axisYFormat != null) {
583          <text>
584          tickOptions: {
585              formatString: "@axisYFormat"
586          },
587          </text>
588        }
589        @if (minY != null) {
590            @:min: @minY,
591        }
592        @if (maxY != null) {
593            @:max: @maxY,
594        }
595        pad: 0
596      }
597    },
598    gridPadding: { left: 50, right: 10 },
599    cursor: {
600      show: true,
601      showTooltip: false,
602      zoom: true,
603      clickReset: false,
604      dblClickReset: false,
605      constrainZoomTo: 'x'
606    }
607  });
608  </text>
609}
Note: See TracBrowser for help on using the repository browser.