@* HeuristicLab * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . *@ @helper AjaxDataRenderer() { } @helper LineChartTime(string destinationTag, string url, string title = "", double? minY = null, double? maxY = null, string axisYFormat = null) { } @helper RefreshChart(string destinationTag, string url, string startDate, string endDate) { $.ajax({url: "@(new HtmlString(url))?start=" + @startDate + "&end=" + @endDate, datatype: "json", success: function(result) { for (var i = 0; i < result.length; i++) { @(destinationTag)Plot.series[i].data = result[i]; } @(destinationTag)Plot.replot({ resetAxes: true }) }}); } @helper ResizeCharts() { function resizeCharts(caller) { //If current plot is collapsed if($(caller).css("display") == "none") { //Display the contents of chartContainer ResizeOpenClose($(caller).siblings(".collapse")); //Reset barWidth for bar charts $.each(window[caller.id].series, function(index, series) { series.barWidth = undefined; }); //Replot the chart with same name as element id window[caller.id].replot({ resetAxes: false }); //Hide the contents of the current div ResizeOpenClose($(caller).siblings(".collapse")); } //Current plot is expanded else { //Reset barWidth for bar charts $.each(window[caller.id].series, function(index, series) { series.barWidth = undefined; }); //Replot the chart with same name as element id window[caller.id].replot({ resetAxes: false }); } } $(window).resize(function() { $("div.jqplot-target",".chartContainer").each(function() { var potentialTab = $(this).parent().parent().parent(); //If the section is tabular and currently hidden if(potentialTab.hasClass("tabSection") && potentialTab.css("display") == "none") { ResizeOpenCloseTabular(potentialTab); resizeCharts(this); ResizeOpenCloseTabular(potentialTab); } else { resizeCharts(this); } }); }); } @helper NumberPages(string records, string limit, string container, string functionName, string currentPage = null) { if(@(records).length > @limit) { $("#@container").append('') var pages = Math.floor(@(records).length/@(limit)) + 1; for(var i=0; i < pages; i++) { $("#" + "@container").append('' + (i + 1) + '') } if(@currentPage != null) { $("#@(container)Page" + @currentPage).css('color','#F7921D'); } else { $("#@(container)Page1").css('color','#F7921D'); } $(".page").click(function () { pageNumber = $(this).html(); @(functionName)(); }); if(@currentPage != null) { @(records).splice(0,(@(currentPage)-1)*@(limit)); if (@(records).length > @(limit)) { @(records).splice(@(limit), @(records).length - @(limit)); } } else { @(records).splice(@(limit), @(records).length - @(limit)); } } } @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) { var GetRequest = "?userName=" + @(userName); @if (startDate != null) { @:if(@(startDate)!=null) { @:GetRequest += "&start=" + @startDate; @:} } @if (endDate != null) { @:if(@(endDate)!=null) { @:GetRequest += "&end=" + @endDate; @:} } @if (jobId != null) { @:if(@(jobId)!=null) { @:GetRequest += "&jobId=" + @jobId; @:} } @if (taskState != null) { @:if(@(taskState)!=null) { @:GetRequest += "&taskState=" + @taskState; @:} } $.ajax({ async: false, url: "@(new HtmlString(url))" + GetRequest, datatype: "json", success: function(result) { if(@(userName) == null) { $("#@(destinationTag)").append( '
' + '

Please select a user!

' + '
' ) } else if(result.length==0) { $("#@(destinationTag)").append( '
' + '

' + @userName + ' has no tasks for the specified filters!

' + '
' ) } else { var waitTime; var transferTime; var runTime; var seriesDescriptions = ["Time waiting","Time transferring","Time calculating"]; //Checks if multipage display, if it is then trims results to //the results for the page to be displayed @ChartHelper.NumberPages("result", limit, destinationTag, functionName, pageNumber) //Globally accesible, for use when resizing, eliminates extra DB request window["numberTasks"] = result.length; //Set display of all errors to none, errors matching the tasks will be reset below $("#@(destinationTag)").find(".errorContainer, .errorTitle, .errorTask, .errorMessage").css('display','none'); //For each result create a seperate collapsable section with a chart and info label for(var i = 0; i < result.length; i++){ $("#" + "@(destinationTag)").append( '
' + '

Task ' + result[i].Key + '

' + '' + '
' + '' + '
' ) //Re-enables the error display if any of the tasks on the page have Ids matching //those of errors $(".errorTask","#" + "@(destinationTag)").each(function() { if($(this).html()==result[i].Key) { $("#@(destinationTag)" + result[i].Key + "PlotTitle").css("color","red"); $("#@(destinationTag)" + result[i].Key + "PlotTitle").append(" - ERROR"); $(".errorContainer, .errorTitle, .underline","#@(destinationTag)").css('display','inline-block'); $(this).css('display','inline-block'); $(this).next().css('display','inline-block'); } }); waitTime = [result[i].Value[0]]; transferTime = [result[i].Value[1]]; runTime = [result[i].Value[2]]; window["@(destinationTag)Plot" + i] = $.jqplot("@(destinationTag)Plot" + i, [waitTime,transferTime,runTime], { seriesDefaults:{ renderer:$.jqplot.BarRenderer, shadowAngle: 135, pointLabels: {show: true, formatString: '%.3f'} }, series:[ {label:'Waiting'}, {label:'Transferring'}, {label:'Calculating'} ], legend: { show: true, location: 'e', placement: 'outside' }, axes: { xaxis: { renderer: $.jqplot.CategoryAxisRenderer, showLabel: false, pad: 0 }, yaxis: { pad: 0 } }, cursor: { showTooltip: false } }); /* Bind a datalistener to each chart and display details of clicked upon data in the label below the chart */ $("#" + "@(destinationTag)Plot" + i).bind('jqplotDataClick', function (ev, seriesIndex, pointIndex, data) { $(this).siblings("label").html(seriesDescriptions[seriesIndex] + ": " + data[1]); }); CollapsedByDefault(document.getElementById("@(destinationTag)Plot" + i)); } } }});
} @helper SetStreamingProperties(int refresh, int chartLength, int upperY) { //Refresh time (in millisec) var refreshRate = @(refresh); //Number of data points on chart var chartSize = @(chartLength); //Amount to add to max Y value var upperYBuffer = @(upperY); //Used to return a string containing the names of the series //to be used in plot creation function GetSeries(numberData,dataName){ var result = "["; for(i=0; i < numberData; i++) { if(i < numberData -1) { result += dataName + i + ","; } else { result += dataName + i + "]"; } } return result; } } @helper CreateStreamChart(string dataName, string destinationTag, string url, string title, string format = null, double? maxY = null) { //Get current time, used to create initial values var @(dataName)CurrentDate = (new Date()).getTime(); var @(dataName)Data = []; var @(dataName)CurrentValue = []; //Get the most recent value(s) from the given URL $.ajax({ async: false, url: '@(url)', datatype: "json", success: function (result) { for(i = 0; i < result.length; i++) { @(dataName)CurrentValue[i] = result[i]; } } }); //Create a chartSize worth of data using CurrentDate and CurrentValue //for each CurrentValue for(i = 0; i < @(dataName)CurrentValue.length; i++) { window["@(dataName)Data" + i] = []; for (j = 0; j < chartSize; j++) { window[ "@(dataName)Data" + i].push([@(dataName)CurrentDate - (chartSize - 1 - j) * refreshRate, @(dataName)CurrentValue[i]]); } } //Options for the chart to be created var @(destinationTag)PlotOptions = { title: "@title", axes: { xaxis: { numberTicks: 4, renderer: $.jqplot.DateAxisRenderer, tickOptions: { formatString: '%H:%M:%S' }, min: window["@(dataName)Data" + 0][0][0], max: window["@(dataName)Data" + 0][window["@(dataName)Data" + 0].length - 1][0] }, yaxis: { @if (format != null) { tickOptions: { formatString: "@format", }, } min: 0, @if (maxY != null) { @:max: @maxY, } else { @:max: window["@(dataName)Data" + 0][window["@(dataName)Data" + 0].length - 1][1] + upperYBuffer, } numberTicks: 6 } }, seriesDefaults: { rendererOptions: { smooth: true }, markerOptions: { show: false } } }; //Declares the jqPlot variable, evals the string of series returned //from getSeries which allows for any number of series window[ "@(destinationTag)Plot"] = $.jqplot('@destinationTag', eval(GetSeries(@(dataName)CurrentValue.length,"@(dataName)Data")), @(destinationTag)PlotOptions); } @helper UpdateStreamChart(string dataName, string destinationTag, string url, string fixedY = null) { //If the data is beyond chartSize use shift to trim one off the end for(i = 0; i < @(dataName)CurrentValue.length; i++) { if (window["@(dataName)Data" + i].length > chartSize - 1) { window["@(dataName)Data" + i].shift(); } } //Get the up-to-date data, each result assigned to it's own array $.ajax({ async: false, url: '@(url)', datatype: "json", success: function (result) { for(i = 0; i < result.length; i++) { window[ "@(dataName)Data" + i].push([(new Date()).getTime(), result[i]]); } } }); //If the plot exists currently destroy it if ( @(destinationTag)Plot) { @(destinationTag)Plot.destroy(); } //Assign series for(i = 0; i < @(dataName)CurrentValue.length; i++) { @(destinationTag)Plot.series[i].data = window["@(dataName)Data" + i]; } //Recalculate x and possibly y axis max and mins @(destinationTag)PlotOptions.axes.xaxis.min = window["@(dataName)Data" + 0][0][0]; @(destinationTag)PlotOptions.axes.xaxis.max = window["@(dataName)Data" + 0][window["@(dataName)Data" + 0].length - 1][0]; @if (fixedY == null) { @:@(destinationTag)PlotOptions.axes.yaxis.max = window["@(dataName)Data" + 0][window["@(dataName)Data" + 0].length - 1][1] + upperYBuffer; } //Re-assigns the jqPlot variable, evals the string of series returned //from getSeries which allows for any number of series @(destinationTag)Plot = $.jqplot('@destinationTag', eval(GetSeries(@(dataName)CurrentValue.length,"@(dataName)Data")), @(destinationTag)PlotOptions); } @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) { var GetRequest = ""; @if (startDate != null) { @:if(@(startDate)!=null) { @:if(GetRequest == "") { @:GetRequest += "?start=" + @startDate; @:} @:else { @:GetRequest += "&start=" + @startDate; @:} @:} } @if (endDate != null) { @:if(@(endDate)!=null) { @:if(GetRequest == "") { @:GetRequest += "?end=" + @endDate; @:} @:else { @:GetRequest += "&end=" + @endDate; @:} @:} } @if (userName != null) { @:if(@(userName)!=null) { @:if(GetRequest == "") { @:GetRequest += "?userName=" + @userName; @:} @:else { @:GetRequest += "&userName=" + @userName; @:} @:} } @if (slaveId != null) { @:if(@(slaveId)!=null) { @:if(GetRequest == "") { @:GetRequest += "?slaveId=" + @slaveId; @:} @:else { @:GetRequest += "&slaveId=" + @slaveId; @:} @:} } $.ajax({ async: false, url: "@(new HtmlString(url))" + GetRequest, datatype: "json", success: function(result) { //Set chart names for use in creation below, must be set identically in //ResizeSlaves var slaveChartNames = ["TotalUsedCores","TotalUsedMemory","CPUUtilization"]; var destTag = eval("@(destinationTag)"); if(typeof eval("@(destinationTag)") != "string") { destTag = "@(destinationTag)"; } if(result.length == 0) { @if (!singleSlave) { @:$('#' + destTag).html(""); } $('#' + destTag).append( '
' + '

No slave information for the specified filters!

' + '
' ) } else { var time = new Date(); @if (!singleSlave) { @:$('#' + destTag).html(""); //Checks if multipage display, if it is then trims results to //the results for the page to be displayed @ChartHelper.NumberPages("result", limit, destinationTag, functionName, pageNumber) } for(i = 0; i < result.length; i++) { var coreSeries = []; coreSeries[0] = []; coreSeries[1] = []; var memorySeries = []; memorySeries[0] = []; memorySeries[1] = []; var cpuSeries = []; cpuSeries[0] = []; $('#' + destTag).append( '
' + '

Slave ' + result[i][0].SlaveID + '

' + '' + '
' + '
' + '
' + '
'); for(j = 0; j < result[i].length; j++) { time.setTime(result[i][j].Time.replace(/\D/g,'')); coreSeries[0].push([time.toUTCString(),result[i][j].TotalCores]); coreSeries[1].push([time.toUTCString(),result[i][j].UsedCores]); memorySeries[0].push([time.toUTCString(),(result[i][j].TotalMemory / 1000)]); memorySeries[1].push([time.toUTCString(),(result[i][j].UsedMemory / 1000)]); cpuSeries[0].push([time.toUTCString(),result[i][j].CPUUtilization]); } if(result[i].length > 1) { @ChartHelper.LineChartGivenSeries("destTag + slaveChartNames[0]", "i", "coreSeries", "Total/Used Cores") @ChartHelper.LineChartGivenSeries("destTag + slaveChartNames[1]", "i", "memorySeries", "Total/Used Memory", 0) @ChartHelper.LineChartGivenSeries("destTag + slaveChartNames[2]", "i", "cpuSeries", "CPU Utilization", 0, 100, "%.1f%%") } else { @ChartHelper.BarChartGivenSeries("destTag + slaveChartNames[0]", "i", "coreSeries", "Total/Used Cores") @ChartHelper.BarChartGivenSeries("destTag + slaveChartNames[1]", "i", "memorySeries", "Total/Used Memory", 0) @ChartHelper.BarChartGivenSeries("destTag + slaveChartNames[2]", "i", "cpuSeries", "CPU Utilization", 0, 100, "%.1f%%") } for(k = 0; k < slaveChartNames.length; k++) { CollapsedByDefault(document.getElementById(destTag + slaveChartNames[k] + "Plot" + i)); } } } }});
} @helper LineChartGivenSeries(string destinationTag, string chartId, string series, string title, double? minY = null, double? maxY = null, string axisYFormat = null) { window[@(destinationTag) + "Plot" + @(chartId)] = $.jqplot(@(destinationTag) + "Plot" + @(chartId), @series, { title: "@title", axes: { xaxis: { renderer: $.jqplot.DateAxisRenderer, tickOptions:{formatString:'%b %#d, %y'}, pad: 0 }, yaxis: { @if (axisYFormat != null) { tickOptions: { formatString: "@axisYFormat" }, } pad: 0, @if (minY != null) { @:min: @minY, } @if (maxY != null) { @:max: @maxY, } } }, gridPadding: { left: 50, right: 10 }, cursor: { show: true, showTooltip: false, zoom: true, clickReset: false, dblClickReset: false, constrainZoomTo: 'x' } }); } @helper BarChartGivenSeries(string destinationTag, string chartId, string series, string title, double? minY = null, double? maxY = null, string axisYFormat = null) { window[@(destinationTag) + "Plot" + @(chartId)] = $.jqplot(@(destinationTag) + "Plot" + @(chartId), @series, { title: "@title", seriesDefaults:{ renderer:$.jqplot.BarRenderer, shadowAngle: 135, pointLabels: {show: true, formatString: '%.2f'} }, axes: { xaxis: { renderer: $.jqplot.CategoryAxisRenderer, tickOptions:{formatString:'%b %#d, %y'}, pad: 0 }, yaxis: { @if (axisYFormat != null) { tickOptions: { formatString: "@axisYFormat" }, } pad: 0, @if (minY != null) { @:min: @minY, } @if (maxY != null) { @:max: @maxY, } } }, gridPadding: { left: 50, right: 10 }, cursor: { show: true, showTooltip: false, zoom: true, clickReset: false, dblClickReset: false, constrainZoomTo: 'x' } }); }