From daab977655f12a0c9d42c24549da44f5a40f849f Mon Sep 17 00:00:00 2001 From: mgerb42 Date: Sun, 20 Dec 2015 21:11:54 -0600 Subject: [PATCH] more graph work --- app.js | 1 + models/temperature.js | 2 +- public/javascripts/sensor_information.js | 238 +++++++++++++++++++---- public/stylesheets/style.css | 7 + routes/api.js | 55 ++++-- routes/sensors.js | 23 ++- views/sensor_information.ejs | 62 ++++-- 7 files changed, 316 insertions(+), 72 deletions(-) diff --git a/app.js b/app.js index 86ce3b2..36a5f6b 100644 --- a/app.js +++ b/app.js @@ -56,6 +56,7 @@ app.use(function(req, res, next) { // development error handler // will print stacktrace + /* if (app.get('env') === 'development') { app.use(function(err, req, res, next) { diff --git a/models/temperature.js b/models/temperature.js index d20142b..f099d95 100644 --- a/models/temperature.js +++ b/models/temperature.js @@ -3,7 +3,7 @@ var mongoose = require('mongoose'); var temperatureSchema = new mongoose.Schema({ temperature: Number, humidity: Number, - location: String, + location: {type : String, default : "Undefined Location"}, updated: {type: Date, default: Date.now} }); diff --git a/public/javascripts/sensor_information.js b/public/javascripts/sensor_information.js index 475bcb5..1085411 100644 --- a/public/javascripts/sensor_information.js +++ b/public/javascripts/sensor_information.js @@ -1,15 +1,51 @@ $(document).ready(function(){ + displayChart("#info-chart-year", "#legend-year", 2015, null); + displayChart("#info-chart-month", "#legend-month", 2015, 9); + +}); + +$("#option-year").on("change", function(){ + + var year = this.value; + + displayChart("#info-chart-year", "#legend-year", year, null); + +}); + +$("#option-month").on("change", function(){ + + var text = this.options[this.selectedIndex].text; + var month = this.value; + var year = text.substring(text.length, text.length -4); + + displayChart("#info-chart-month", "#legend-month", year, month); + +}); + +function displayChart(chart_id, chart_legend_id, year, month){ + Chart.defaults.global.responsive = true; var loc = $("#sensor-location").text(); - console.log(loc); loc = loc.split().join("+"); - $.get("/api/sensorbylocation?location=" + loc, function(request){ + var api_url = "/api/sensorbylocation"; + + if (month ==null){ + api_url += "/year?location=" + loc + "&year=" + year; + } + + else { + api_url += "/month?location=" + loc + "&month=" + month + "&year=" + year; + console.log("api 2"); + } + + $.get(api_url, function(request){ var json = request; var data = {labels : [], datasets : []}; + console.log(json); data.datasets.push({ label: "Max Temperature", @@ -33,46 +69,180 @@ $(document).ready(function(){ }); for (var i in json){ - data.labels.push(json[i]._id.month + "/" + json[i]._id.day + "/" + json[i]._id.year); + + if (month == null){ + data.labels.push(json[i]._id.month + "/" + json[i]._id.day); + } + else { + data.labels.push(json[i]._id.day); + } + data.datasets[0].data.push(json[i].max); data.datasets[1].data.push(json[i].min); } - - - // Get context with jQuery - using jQuery's .get() method. - var ctx = $("#info-chart").get(0).getContext("2d"); + var ctx = $(chart_id).get(0).getContext("2d"); // This will get the first returned node in the jQuery collection. var myLineChart = new Chart(ctx).Line(data); + $(chart_legend_id).html(myLineChart.generateLegend()); + }); - -}); +} -var test123 = { - labels: ["January", "February", "March", "April", "May", "June", "July"], - datasets: [ - { - label: "My First dataset", - fillColor: "rgba(220,220,220,0.2)", - strokeColor: "rgba(220,220,220,1)", - pointColor: "rgba(220,220,220,1)", - pointStrokeColor: "#fff", - pointHighlightFill: "#fff", - pointHighlightStroke: "rgba(220,220,220,1)", - data: [65, 59, 80, 81, 56, 55, 40] - }, - { - label: "My Second dataset", - fillColor: "rgba(151,187,205,0.2)", - strokeColor: "rgba(151,187,205,1)", - pointColor: "rgba(151,187,205,1)", - pointStrokeColor: "#fff", - pointHighlightFill: "#fff", - pointHighlightStroke: "rgba(151,187,205,1)", - data: [28, 48, 40, 19, 86, 27, 90] - } - ] -}; \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + +Chart.defaults.global = { + // Boolean - Whether to animate the chart + animation: true, + + // Number - Number of animation steps + animationSteps: 60, + + // String - Animation easing effect + // Possible effects are: + // [easeInOutQuart, linear, easeOutBounce, easeInBack, easeInOutQuad, + // easeOutQuart, easeOutQuad, easeInOutBounce, easeOutSine, easeInOutCubic, + // easeInExpo, easeInOutBack, easeInCirc, easeInOutElastic, easeOutBack, + // easeInQuad, easeInOutExpo, easeInQuart, easeOutQuint, easeInOutCirc, + // easeInSine, easeOutExpo, easeOutCirc, easeOutCubic, easeInQuint, + // easeInElastic, easeInOutSine, easeInOutQuint, easeInBounce, + // easeOutElastic, easeInCubic] + animationEasing: "easeOutQuart", + + // Boolean - If we should show the scale at all + showScale: true, + + // Boolean - If we want to override with a hard coded scale + scaleOverride: false, + + // ** Required if scaleOverride is true ** + // Number - The number of steps in a hard coded scale + scaleSteps: null, + // Number - The value jump in the hard coded scale + scaleStepWidth: null, + // Number - The scale starting value + scaleStartValue: null, + + // String - Colour of the scale line + scaleLineColor: "rgba(0,0,0,.1)", + + // Number - Pixel width of the scale line + scaleLineWidth: 1, + + // Boolean - Whether to show labels on the scale + scaleShowLabels: true, + + // Interpolated JS string - can access value + scaleLabel: "<%=value%>", + + // Boolean - Whether the scale should stick to integers, not floats even if drawing space is there + scaleIntegersOnly: true, + + // Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value + scaleBeginAtZero: false, + + // String - Scale label font declaration for the scale label + scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", + + // Number - Scale label font size in pixels + scaleFontSize: 12, + + // String - Scale label font weight style + scaleFontStyle: "normal", + + // String - Scale label font colour + scaleFontColor: "#666", + + // Boolean - whether or not the chart should be responsive and resize when the browser does. + responsive: false, + + // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container + maintainAspectRatio: true, + + // Boolean - Determines whether to draw tooltips on the canvas or not + showTooltips: true, + + // Function - Determines whether to execute the customTooltips function instead of drawing the built in tooltips (See [Advanced - External Tooltips](#advanced-usage-custom-tooltips)) + customTooltips: false, + + // Array - Array of string names to attach tooltip events + tooltipEvents: ["mousemove", "touchstart", "touchmove"], + + // String - Tooltip background colour + tooltipFillColor: "rgba(0,0,0,0.8)", + + // String - Tooltip label font declaration for the scale label + tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", + + // Number - Tooltip label font size in pixels + tooltipFontSize: 14, + + // String - Tooltip font weight style + tooltipFontStyle: "normal", + + // String - Tooltip label font colour + tooltipFontColor: "#fff", + + // String - Tooltip title font declaration for the scale label + tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", + + // Number - Tooltip title font size in pixels + tooltipTitleFontSize: 14, + + // String - Tooltip title font weight style + tooltipTitleFontStyle: "bold", + + // String - Tooltip title font colour + tooltipTitleFontColor: "#fff", + + // Number - pixel width of padding around tooltip text + tooltipYPadding: 6, + + // Number - pixel width of padding around tooltip text + tooltipXPadding: 6, + + // Number - Size of the caret on the tooltip + tooltipCaretSize: 8, + + // Number - Pixel radius of the tooltip border + tooltipCornerRadius: 6, + + // Number - Pixel offset from point x to tooltip edge + tooltipXOffset: 10, + + // String - Template string for single tooltips + tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>", + + // String - Template string for multiple tooltips + multiTooltipTemplate: "<%= value %>", + + // Function - Will fire on animation progression. + onAnimationProgress: function(){}, + + // Function - Will fire on animation completion. + onAnimationComplete: function(){} + +} \ No newline at end of file diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index a858b71..1dc7d63 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -248,4 +248,11 @@ a { .gist-data{ max-height: 500px; max-width: 600px; +} + +.chart-legend li span{ + display: inline-block; + width: 12px; + height: 12px; + margin-right: 5px; } \ No newline at end of file diff --git a/routes/api.js b/routes/api.js index e33d5d2..102c62f 100644 --- a/routes/api.js +++ b/routes/api.js @@ -23,23 +23,24 @@ router.get('/allsensors', function(req, res, next) { }); -router.get('/sensorbylocation', function(req, res, next) { +router.get('/sensorbylocation/year', function(req, res, next) { var loc = req.query.location; - var year = req.query.year; + var ye = req.query.year; - if (year == null){ + if (ye == null){ var date = new Date(); - year = date.getFullYear(); + ye = date.getFullYear(); } //query finds a entries in a collection based on location and the year specified //they are then grouped by date and sorted by date as well - temperature.aggregate([ {$match : {location : loc, updated : {$gte : new Date('1 Jan, ' + year), $lt : new Date('1 Jan ' + year +1)}}}, - {$group : { _id : {location : "$location", month: {$month: "$updated" }, day: { $dayOfMonth: "$updated" }, year: { $year: "$updated" }}, + temperature.aggregate([ {$project : {location : 1, temperature : 1, year : {$year : "$updated"}, month : {$month : "$updated"}, day : {$dayOfMonth : "$updated"}}}, + {$match : {location : loc, year : parseInt(ye)}}, + {$group : {_id : {location : "$location", day: "$day", month : "$month", year : "$year"}, max : {$max : "$temperature"}, min : {$min : "$temperature"}}}, - {$sort : {"_id.month" : 1, "_id.day" : 1, "_id.year" : 1}}]).exec(function(err, info){ + {$sort : {"_id.month" : 1, "_id.day" : 1}}]).exec(function(err, info){ console.log(info); res.setHeader('Content-Type', 'application/json'); @@ -49,21 +50,43 @@ router.get('/sensorbylocation', function(req, res, next) { }); -router.post('/', function(req, res,next) { +router.get('/sensorbylocation/month', function(req, res, next) { + + var loc = req.query.location; + var ye = req.query.year; + var mo = req.query.month; + var date = new Date(); + + if (ye == null){ + ye = date.getFullYear(); + } + + if (mo == null){ + mo = date.getMonth(); + } + + console.log(ye + "/" + mo); + //query finds a entries in a collection based on location and the year specified + //they are then grouped by date and sorted by date as well + temperature.aggregate([ {$project : {location : 1, temperature : 1, year : {$year : "$updated"}, month : {$month : "$updated"}, day : {$dayOfMonth : "$updated"}}}, + {$match : {location : loc, year : parseInt(ye), month : parseInt(mo)}}, + {$group : {_id : {location : "$location", day: "$day", month : "$month", year : "$year"}, + max : {$max : "$temperature"}, + min : {$min : "$temperature"}}}, + {$sort : {"_id.day" : 1}}]).exec(function(err, info){ + + console.log(info); + res.setHeader('Content-Type', 'application/json'); + res.send(JSON.stringify(info, null, 4)); + + }); }); + module.exports = router; - - - - - - - - diff --git a/routes/sensors.js b/routes/sensors.js index ccf567e..4bf41aa 100644 --- a/routes/sensors.js +++ b/routes/sensors.js @@ -74,9 +74,30 @@ router.get('/information', function(req, res, err){ if (sensor_location == null){ res.redirect('/404'); } + else{ + temperature.aggregate([{$project : {location : "$location", year : {$year : "$updated"}, month : {$month : "$updated"}}}, + {$match : {location : sensor_location}}, + {$group : {_id : {year : "$year", month : "$month", location : "$location"}}}, + {$sort : {"_id.year" : 1, "_id.month" : 1}}]).exec(function(err, info){ + console.log(info); - res.render('sensor_information', {info : {location : sensor_location}}); + //generate list of unique years to display in dropdown menu + var years_list = []; + for (var i in info){ + if (years_list.indexOf(info[i]._id.year) > -1){ + + } + else { + years_list.push(info[i]._id.year); + } + } + + res.render('sensor_information', {info, years_list}); + + }); + + } }); module.exports = router; diff --git a/views/sensor_information.ejs b/views/sensor_information.ejs index b3dd967..a55425a 100644 --- a/views/sensor_information.ejs +++ b/views/sensor_information.ejs @@ -11,33 +11,54 @@
<% include ../public/html/navbar.html %> - +<% var monthNames = ["January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"]; %>

-

<%=info.location%>

+

<%=info[0]._id.location%>



- +
+
+ + +
+
+ +
+ +
+
+ +
+
+ + +
+
+ +
+

Month

+ +
+
- - - - - -
-
-
-
-
-
-
-
-
-
-
-


@@ -49,6 +70,7 @@ glyphicons.com + <% include layoutBottom.ejs %>