/* Authors: Tristan Wright, July 2012, Lillian Gray 2017-2020 This reads the json formatted data generated by data_gen.py the data is piped into the Google Charts API and a graph with controls are made If more buildings are added increment buildingNum and add a new color to buildingColors Benchmark functions or sections by wrapping them in: console.log(var a = new Date()-0); console.log(var b = new Date()-0 - a); */ //init globals //adaptive screen height. var graphHeight = Math.floor($(document).height() * .6); $("#dashboard").css("height", graphHeight+70); //chart data source is global so we don't have to reload every time. var lineChartJSONData = jQuery.ajax({ url: "raw_line_chart.txt", //location of data file dataType: "json", async: false }).responseText; var lineChartData; var dashboard; var controlWrapper; var chartWrapper; const buildingNum = 8; var whichBuildings = new Array(); for(i=0; i < buildingNum; i++){ whichBuildings[i] = true; } //change colors here var buildingColors = new Array( '#9c1c34', '#0A22af', '#ff381a','#00ff00', '#009944','#50D8F1','#e9af32', '#E07628'); //Sets initial range of site to the last month var today = new Date((new Date).toDateString()); var endDate = new Date(today); var startDate = new Date(today.setMonth(today.getMonth() - 1)); //for permalink parsing var URLComponents = document.URL.split('?'); if(URLComponents.length==2){ var permalinked = true; var args = URLComponents[1]; var argsArray = args.split("+"); var startTemp = parseDate(argsArray[0]); var endTemp = parseDate(argsArray[1]); var whichArgs = parseInts(argsArray[2].split("")); for(i=0; i<whichArgs.length; i++) whichBuildings[whichArgs[i]] = !whichBuildings[whichArgs[i]]; if(startTemp < endTemp){ var startDate = startTemp; var endDate = endTemp; } } function flipAndRedraw(which){ whichBuildings[which] = !whichBuildings[which]; if(which===0) //Adds or removes total options for chart handleTotalOptions(whichBuildings[0]); drawLineChart(); } function handleTotalOptions(totalVisible){ if(totalVisible===true){ //adds options for separate series for total data chartWrapper.setOption('series',{0:{'targetAxisIndex': 1}}); chartWrapper.setOption('vAxes', {1:{ 'title':'Total Campus Usage in Kilowatts', 'titleColor':buildingColors[0], 'textColor':buildingColors[0], 'gridlines':{'color':'transparent'}, 'baselineColor':'transparent' }}); } else{ //removes options for total data chartWrapper.setOption('series',{}); } } function drawLineChart(){ // column 0 is date and should always be included var visibleColumns = [0]; var visibleColors = []; for(i=0;i<whichBuildings.length;i++){ if(whichBuildings[i]){ //since column 0 is date, column index is one greater for API visibleColumns.push(i+1); visibleColors.push(buildingColors[i]); } } lineChartData.setColumns(visibleColumns); chartWrapper.setOption('colors', visibleColors) // Total is not displayed in controlWrapper if it is enabled if(whichBuildings[0]===true){ controlWrapper.setOption('ui.chartOptions.colors', visibleColors.slice(1)); //Control wrapper columns are based on indexes of chart columns, include every index but 1 for Total var controlWrapperColumns = [0]; for(i=2; i<visibleColumns.length;i++){ controlWrapperColumns.push(i); } controlWrapper.setOption('ui.chartView.columns', controlWrapperColumns); } else{ controlWrapper.setOption('ui.chartOptions.colors', visibleColors); controlWrapper.setOption('ui.chartView.columns', null); } dashboard.draw(lineChartData); } function initializeLineChart(){ lineChartData = new google.visualization.DataView(new google.visualization.DataTable(lineChartJSONData)); dashboard = new google.visualization.Dashboard(document.getElementById('dashboard')); //changes time range if most current data isn't available var latestEntryDate = new Date(lineChartData.getValue(lineChartData.getNumberOfRows()-1, 0)) if(!permalinked && latestEntryDate!=endDate){ endDate = new Date(latestEntryDate) startDate = new Date(latestEntryDate.setMonth(latestEntryDate.getMonth() - 1)); } //settings for control bar below chart controlWrapper = new google.visualization.ControlWrapper({ 'controlType': 'ChartRangeFilter', 'containerId': 'control', 'options': { // Filter by the date axis. 'filterColumnIndex': 0, 'ui': { 'chartType': 'LineChart', 'chartOptions': { 'chartArea': {'width': '100%', 'height': 75}, 'colors': buildingColors.slice(1), 'hAxis': {'baselineColor': 'none'}}, //1 day in milliseconds = 24 * 60 * 60 * 1000 = 86,400,000 'minRangeSize': 86400000 } //close ui }, // Initial range: (yyyy-mm-dd) 'state': {'range': {'start': startDate, 'end': endDate}} }); //chart settings chartWrapper = new google.visualization.ChartWrapper({ 'chartType': 'LineChart', 'containerId': 'lineChart', 'options':{ // Use the same chart area width as the control for axis alignment. 'width': '100%','height': graphHeight, 'fontName': 'Georgia', 'vAxis': {'title': 'Individual Building Usage in Kilowatts'}, 'hAxis': { 'slantedText': true, 'format': 'EEE MMM d, yyyy', //ICU Simple Date Format 'textStyle': {'fontSize':14}, 'gridlines': {'count':0, 'color': '#fff'}}, 'colors': buildingColors, 'legend': 'none' },//close options }); //close chart_wrapper //event handler saves date google.visualization.events.addListener(controlWrapper, 'statechange', function(){ startDate = controlWrapper.getState().range.start; endDate = controlWrapper.getState().range.end; } ); dashboard.bind(controlWrapper, chartWrapper); //bind control to chart if(whichBuildings[0]===true){ handleTotalOptions(whichBuildings[0]); } drawLineChart(); } function parseDate(urlArg){ var dateArr = urlArg.split("-"); //month is zero-indexed return new Date(parseInt(dateArr[0]), parseInt(dateArr[1]) - 1, parseInt(dateArr[2])); } function parseInts(strArray){ var a = new Array(); for(i=0; i < strArray.length; i++) a.push(parseInt(strArray[i])); return a; } // Generating a permalink function genPermalink(){ //month is zero-indexed var startStr = startDate.getFullYear()+"-"+(startDate.getMonth() + 1)+"-"+startDate.getDate(); var endStr = endDate.getFullYear()+"-"+(endDate.getMonth() + 1)+"-"+endDate.getDate(); var disabledBuildings = ""; for(i=0; i < buildingNum; i++){ if(!whichBuildings[i]) disabledBuildings += i; } var permalink = URLComponents[0]+"?"+startStr+"+"+endStr+"+"+disabledBuildings; //Copies permalink and puts permalink in text box next to the button var plinkTextField = document.getElementById('plink'); plinkTextField.value = permalink; plinkTextField.select(); document.execCommand('copy'); //Fades tooltip in and out var plinkButton = document.querySelector('.getPlink') plinkButton.classList.add('active') plinkButton.classList.remove('inactive') setTimeout(function(){ plinkButton.classList.remove('active') setTimeout(function(){ plinkButton.classList.add('inactive') }, 1000); }, 1000); } $('#csvDownload').click(function () { //prepares and then downloads a csv file based on what is currently shown in the chart //creates csvString using same visible data as chart var dataView = new google.visualization.DataView(lineChartData); var filteredRows = dataView.getFilteredRows([{column: 0, minValue: startDate, maxValue: endDate}]); dataView.setRows(filteredRows); var csvString = google.visualization.dataTableToCsv(dataView); //generates header to append to beginning of csvString var csvHeader = ""; for(i=0; i < lineChartData.getNumberOfColumns(); i++){ csvHeader += lineChartData.getColumnLabel(i); csvHeader += ","; } csvString = csvHeader + "\n" + csvString; //downloads csv var encodedUri = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csvString); this.href = encodedUri; this.download = 'energy-monitoring-data.csv'; this.target = '_blank'; }); function changeDashboard(button) { if(button=="about") { if(document.getElementById("aboutText").classList.toggle('displayNone')){ document.getElementById("lineChart").classList.remove('displayNone'); document.getElementById("control").classList.remove('displayNone'); document.getElementById("aboutButton").innerHTML = "About"; } else { document.getElementById("lineChart").classList.add('displayNone'); document.getElementById("control").classList.add('displayNone'); document.getElementById("howToUse").classList.add('displayNone'); document.getElementById("aboutButton").innerHTML = "Back"; document.getElementById("howToButton").innerHTML = "How To Use"; } } else if(button=="howToUse") { if(document.getElementById("howToUse").classList.toggle('displayNone')){ document.getElementById("lineChart").classList.remove('displayNone'); document.getElementById("control").classList.remove('displayNone'); document.getElementById("howToButton").innerHTML = "How To Use"; } else { document.getElementById("lineChart").classList.add('displayNone'); document.getElementById("control").classList.add('displayNone'); document.getElementById("aboutText").classList.add('displayNone'); document.getElementById("aboutButton").innerHTML = "About"; document.getElementById("howToButton").innerHTML = "Back"; } } }