Column selector. NPM-based build environment.

master
ben-burlingham 10 years ago
parent df595d6c5e
commit 9db3080d34
  1. BIN
      .sass-cache/5c9c699b536baf3fb8147b977bb72448ea259feb/index.scssc
  2. BIN
      bar-display.png
  3. 2
      client/_stations.json
  4. 83
      client/behaviors.js
  5. 227
      client/chart.js
  6. 89
      client/data.js
  7. 2
      client/init.js
  8. 159
      css/index.css
  9. 158
      index.html
  10. 24
      package.json
  11. BIN
      raw/bar-display.psd
  12. 3
      readme.md
  13. 52
      sass/chart.scss
  14. 22
      sass/index.scss
  15. 18
      sass/map.scss
  16. 116
      sass/options.scss
  17. 184
      server/assemble.js
  18. 5
      server/meteo.js
  19. 21
      tasks/sass.js
  20. 11
      tasks/watch.js

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because one or more lines are too long

@ -1,18 +1,17 @@
'use strict'; 'use strict';
var BuoyAnalysisBehaviors = { var BuoyAnalysisBehaviors = {
stationClick: function() {
},
stationMouseover: function() {
},
/**
*
*/
reticleDrag: function(d) { reticleDrag: function(d) {
}, },
/**
*
*/
reticleDragEnd: function() { reticleDragEnd: function() {
var x = d3.mouse(this)[0]; var x = d3.mouse(this)[0];
var y = d3.mouse(this)[1]; var y = d3.mouse(this)[1];
@ -39,10 +38,72 @@ var BuoyAnalysisBehaviors = {
BuoyAnalysisChart.draw(); BuoyAnalysisChart.draw();
}, },
/**
*
*/
reticleResize: function() { reticleResize: function() {
}, },
/**
*
*/
barDisplayClick: function(d) {
var e = d3.select(this);
d3.selectAll('.bar-display .toggle').classed('selected', false);
e.classed('selected', true);
if (e.classed('toggle1')) {
BuoyAnalysisChart.bars.showYears = true;
BuoyAnalysisChart.bars.showMonths = true;
}
else if (e.classed('toggle2')) {
BuoyAnalysisChart.bars.showYears = false;
BuoyAnalysisChart.bars.showMonths = true;
}
else if (e.classed('toggle3')) {
BuoyAnalysisChart.bars.showYears = true;
BuoyAnalysisChart.bars.showMonths = false;
}
BuoyAnalysisChart.draw();
},
/**
*
*/
columnDisplayClick: function(d) {
var e = d3.select(this);
d3.selectAll('.column-display .toggle').classed('selected', false);
e.classed('selected', true);
if (e.classed('toggle1')) {
BuoyAnalysisChart.bars.property = 'ATMP';
}
else if (e.classed('toggle2')) {
BuoyAnalysisChart.bars.property = 'WTMP';
}
else if (e.classed('toggle3')) {
BuoyAnalysisChart.bars.property = 'WVHT';
}
else if (e.classed('toggle4')) {
BuoyAnalysisChart.bars.property = 'WPER';
}
else if (e.classed('toggle5')) {
BuoyAnalysisChart.bars.property = 'WSPD';
}
BuoyAnalysisChart.updateAxes();
BuoyAnalysisChart.draw();
},
/**
*
*/
attachBehaviors: function() { attachBehaviors: function() {
d3.select('#map') d3.select('#map')
.on('click', BuoyAnalysisBehaviors.reticleDragEnd) .on('click', BuoyAnalysisBehaviors.reticleDragEnd)
@ -50,7 +111,13 @@ var BuoyAnalysisBehaviors = {
// .on('drag', BuoyAnalysisBehaviors.reticleDrag) // .on('drag', BuoyAnalysisBehaviors.reticleDrag)
// .on('dragend', BuoyAnalysisBehaviors.reticleDragEnd) // .on('dragend', BuoyAnalysisBehaviors.reticleDragEnd)
// ); // );
},
d3.selectAll('.bar-display .toggle')
.on('click', BuoyAnalysisBehaviors.barDisplayClick);
d3.selectAll('.column-display .toggle')
.on('click', BuoyAnalysisBehaviors.columnDisplayClick);
}
}; };
// d3.selectAll('.detail') // d3.selectAll('.detail')

@ -5,9 +5,31 @@ var BuoyAnalysisChart = {
* *
*/ */
bars: { bars: {
padding: 24, padding: 26,
spacing: 2, spacing: 2,
width: 23, width: 23,
showMonths: true,
showYears: true,
property: 'WTMP',
tickValues: null,
imperialLabel: null,
metricLabel: null,
smallHexValue: null,
largeHexValue: null
},
axis: {
h: 200,
min: 100,
max: 0,
scale: null,
scaleInverted: null,
imperial: null,
metric: null
}, },
/** /**
@ -22,107 +44,202 @@ var BuoyAnalysisChart = {
*/ */
barMonthX: function(d, i) { barMonthX: function(d, i) {
var year = Math.floor(i / 12); var year = Math.floor(i / 12);
return year * BuoyAnalysisChart.bars.width + BuoyAnalysisChart.bars.padding + year * BuoyAnalysisChart.bars.spacing + (i % 12) * 2; return year * BuoyAnalysisChart.bars.width + BuoyAnalysisChart.bars.padding + year * BuoyAnalysisChart.bars.spacing + (i % 12) * 2;
}, },
/** /**
* *
*/ */
draw: function() { appendGradient: function() {
var years = BuoyAnalysisData.calculateYearlyAverages(BuoyAnalysisMap.reticle.stations);
var months = BuoyAnalysisData.calculateMonthlyAverages(BuoyAnalysisMap.reticle.stations);
var chart = d3.select('#chart'); var chart = d3.select('#chart');
var id = 'gradient-year';
var toggles = d3.select('#year-toggles') chart.selectAll('#' + id).remove();
chart.selectAll('*').remove();
var gradient = chart.append("svg:defs") var gradient = chart.append("svg:defs")
.append("svg:linearGradient") .append("svg:linearGradient")
.attr("id", "Gradient1") .attr("id", id)
.attr('gradientTransform', 'rotate(90)') .attr('gradientTransform', 'rotate(90)')
gradient.append("svg:stop") gradient.append("svg:stop")
.attr("offset", "0%") .attr("offset", "0%")
.attr("stop-color", "#6cf7ce") .attr("stop-color", BuoyAnalysisChart.bars.largeHexValue)
.attr("stop-opacity", 1); .attr("stop-opacity", 1);
gradient.append("svg:stop") gradient.append("svg:stop")
.attr("offset", "100%") .attr("offset", "100%")
.attr("stop-color", "#40596F") .attr("stop-color", BuoyAnalysisChart.bars.smallHexValue)
.attr("stop-opacity", 1); .attr("stop-opacity", 1);
},
chart.selectAll('.bar-year').data(years).enter() /**
.append('rect') *
.classed('bar-year', true) */
.attr('fill', 'url("#Gradient1")') appendYearLabels: function() {
.attr('width', 23) var years = BuoyAnalysisData.calculateYearlyAverages(BuoyAnalysisMap.reticle.stations);
.attr('height', BuoyAnalysisData.axis.h)
.attr('x', BuoyAnalysisChart.barYearX)
.attr('y', 0)
chart.selectAll('.mask-year').data(years).enter()
.append('rect')
.classed('.mask-year', true)
.attr('fill', '#fff')
.attr('width', 25)
.attr('height', function(d) {
return BuoyAnalysisData.axis.scale(d.average);
})
.attr('x', function(d, i) {
return BuoyAnalysisChart.barYearX(d, i) - 1;
})
.attr('y', 0)
toggles.selectAll('div').data(years).enter() d3.select('#year-labels').selectAll('div').data(years).enter()
.append('div') .append('div')
.classed('year-toggle', true) .classed('label', true)
.text(function(d) { .text(function(d) {
return d.year.toString().slice(-2); return d.year.toString().slice(-2);
}) })
.attr('x', BuoyAnalysisChart.barYearX) .attr('x', BuoyAnalysisChart.barYearX)
.attr('y', 180) .attr('y', 180)
},
/**
*
*/
appendAxes: function() {
var chart = d3.select('#chart');
chart.selectAll('.axis').remove();
chart.selectAll('.label-axis-y').remove();
chart.append("g") chart.append("g")
.classed('axis', true) .classed('axis', true)
.classed('axis-fahrenheit', true) .classed('axis-imperial', true)
.attr('transform', 'translate(24, 0)') .attr('transform', 'translate(30, 0)')
.attr('fill', '#000') .attr('fill', '#000')
.call(BuoyAnalysisData.axis.fahrenheit); .call(BuoyAnalysisChart.axis.imperial);
chart.append("g") chart.append("g")
.classed('axis', true) .classed('axis', true)
.classed('axis-celsius', true) .classed('axis-metric', true)
.attr('transform', 'translate(871, 0)') .attr('transform', 'translate(871, 0)')
.call(BuoyAnalysisData.axis.celsius); .call(BuoyAnalysisChart.axis.metric);
chart.append('text') chart.append('text')
.classed('label-axis-y', true) .classed('label-axis-y', true)
.attr('text-anchor', 'middle') .attr('text-anchor', 'middle')
.text('F') .text(BuoyAnalysisChart.bars.imperialLabel)
.attr('x', 10) .attr('x', 12)
.attr('y', 15) .attr('y', 15)
chart.append('text') chart.append('text')
.classed('label-axis-y', true) .classed('label-axis-y', true)
.attr('text-anchor', 'middle') .attr('text-anchor', 'middle')
.text('C') .text(BuoyAnalysisChart.bars.metricLabel)
.attr('x', 885) .attr('x', 885)
.attr('y', 15) .attr('y', 15)
},
/**
*
*/
updateAxes: function() {
switch(BuoyAnalysisChart.bars.property) {
case 'ATMP':
BuoyAnalysisChart.bars.tickValues = [8, 12, 16, 20, 24];
BuoyAnalysisChart.bars.imperialLabel = 'F';
BuoyAnalysisChart.bars.metricLabel = 'C';
BuoyAnalysisChart.bars.smallHexValue = '#40596F';
BuoyAnalysisChart.bars.largeHexValue = '#6cf7ce';
break;
case 'WTMP':
BuoyAnalysisChart.bars.tickValues = [10, 13, 15.5, 18.5, 21];
BuoyAnalysisChart.bars.imperialLabel = 'F';
BuoyAnalysisChart.bars.metricLabel = 'C';
BuoyAnalysisChart.bars.smallHexValue = '#40596F';
BuoyAnalysisChart.bars.largeHexValue = '#6cf7ce';
break;
case 'WVHT':
BuoyAnalysisChart.bars.tickValues = [0, 1, 2, 3, 4];
BuoyAnalysisChart.bars.imperialLabel = 'FT';
BuoyAnalysisChart.bars.metricLabel = 'M';
BuoyAnalysisChart.bars.smallHexValue = '#f00';
BuoyAnalysisChart.bars.largeHexValue = '#C8EBF4';
// BuoyAnalysisChart.bars.largeHexValue = '#ff0';
break;
case 'WPER':
BuoyAnalysisChart.bars.tickValues = [5, 7, 9, 11, 13, 15];
BuoyAnalysisChart.bars.imperialLabel = 'SEC';
BuoyAnalysisChart.bars.metricLabel = 'SEC';
BuoyAnalysisChart.bars.smallHexValue = '#20a';
BuoyAnalysisChart.bars.largeHexValue = '#a02';
break;
case 'WSPD':
BuoyAnalysisChart.bars.tickValues = [3, 6, 9, 12];
BuoyAnalysisChart.bars.imperialLabel = 'FT/S';
BuoyAnalysisChart.bars.metricLabel = 'M/S';
BuoyAnalysisChart.bars.smallHexValue = '#f00';
BuoyAnalysisChart.bars.largeHexValue = '#0f0';
break;
};
},
/**
*
*/
draw: function() {
var years = BuoyAnalysisData.calculateYearlyAverages(BuoyAnalysisMap.reticle.stations);
var months = BuoyAnalysisData.calculateMonthlyAverages(BuoyAnalysisMap.reticle.stations);
var chart = d3.select('#chart');
chart.selectAll('.bar-month').data(months).enter() BuoyAnalysisData.setAxisProperties();
.append('rect') BuoyAnalysisChart.appendAxes();
.attr('fill', 'rgba(0, 0, 0, 0.2)') BuoyAnalysisChart.appendGradient();
.attr('width', 1) BuoyAnalysisChart.appendYearLabels();
.attr('height', function(d) {
return BuoyAnalysisData.axis.scaleInverted(d.average) chart.selectAll('.bar-year').remove();
}) chart.selectAll('.mask-year').remove();
.attr('x', BuoyAnalysisChart.barMonthX) chart.selectAll('.bar-month').remove();
.attr('y', function(d) {
return BuoyAnalysisData.axis.h - BuoyAnalysisData.axis.scaleInverted(d.average); if (BuoyAnalysisChart.bars.showYears === true) {
}) chart.selectAll('.bar-year').data(years).enter()
.append('rect')
.classed('bar-year', true)
.attr('fill', 'url("#gradient-year")')
.attr('width', 23)
.attr('height', BuoyAnalysisChart.axis.h)
.attr('x', BuoyAnalysisChart.barYearX)
.attr('y', 0)
chart.selectAll('.mask-year').data(years).enter()
.append('rect')
.classed('.mask-year', true)
.attr('fill', '#fff')
.attr('width', 25)
.attr('height', function(d) {
return Math.max(0, BuoyAnalysisChart.axis.scale(d.average));
})
.attr('x', function(d, i) {
return BuoyAnalysisChart.barYearX(d, i) - 1;
})
.attr('y', 0)
}
if (BuoyAnalysisChart.bars.showMonths === true) {
chart.selectAll('.bar-month').data(months).enter()
.append('rect')
.classed('bar-month', true)
.attr('fill', 'rgba(0, 0, 0, 0.2)')
.attr('width', 1)
.attr('height', function(d) {
return Math.max(0, BuoyAnalysisChart.axis.scaleInverted(d.average));
})
.attr('x', BuoyAnalysisChart.barMonthX)
.attr('y', function(d) {
return BuoyAnalysisChart.axis.h - BuoyAnalysisChart.axis.scaleInverted(d.average);
})
}
} }
}; };

@ -12,16 +12,6 @@ var BuoyAnalysisData = {
end: 2015 end: 2015
}, },
axis: {
h: 200,
min: 100,
max: 0,
scale: null,
scaleInverted: null,
fahrenheit: null,
celsius: null
},
/** /**
* *
*/ */
@ -49,51 +39,74 @@ var BuoyAnalysisData = {
/** /**
* *
*/ */
setAxisProperties: function() { setAxisProperties: function(property, tickValues) {
var json = BuoyAnalysisData.stationJson; var json = BuoyAnalysisData.stationJson;
var property = BuoyAnalysisChart.bars.property;
var tickValues = BuoyAnalysisChart.bars.tickValues;
for (var id in json) { BuoyAnalysisChart.axis.min = 100;
for (var prop in json[id]) { BuoyAnalysisChart.axis.max = 0;
if (prop === 'id' || prop === 'lat' || prop === 'lon' || prop === 'name') {
continue;
}
for (var id in json) {
for (var year = BuoyAnalysisData.years.start; year <= BuoyAnalysisData.years.end; year++) {
for (var i = 0; i < 12; i++) { for (var i = 0; i < 12; i++) {
if (json[id][prop]['m'][i] <= 0) { if (json[id][property + year]['m'][i] <= 0) {
continue; continue;
} }
if (json[id][prop]['m'][i] < BuoyAnalysisData.axis.min) { if (json[id][property + year]['m'][i] < BuoyAnalysisChart.axis.min) {
BuoyAnalysisData.axis.min = json[id][prop]['m'][i]; BuoyAnalysisChart.axis.min = json[id][property + year]['m'][i];
} }
if (json[id][prop]['m'][i] > BuoyAnalysisData.axis.max) { if (json[id][property + year]['m'][i] > BuoyAnalysisChart.axis.max) {
BuoyAnalysisData.axis.max = json[id][prop]['m'][i]; BuoyAnalysisChart.axis.max = json[id][property + year]['m'][i];
} }
} }
} }
} }
// console.warn("MIN: " + BuoyAnalysisData.axis.min + ', MAX: ' + BuoyAnalysisData.axis.max) // console.log(BuoyAnalysisChart.bars.property)
// console.log(BuoyAnalysisChart.axis.min)
// console.warn(BuoyAnalysisChart.axis.max)
BuoyAnalysisData.axis.scale = d3.scale.linear() BuoyAnalysisChart.axis.scale = d3.scale.linear()
.domain([BuoyAnalysisData.axis.min, BuoyAnalysisData.axis.max]) .domain([BuoyAnalysisChart.axis.min, BuoyAnalysisChart.axis.max])
.range([BuoyAnalysisData.axis.h, 0]); .range([BuoyAnalysisChart.axis.h, 0]);
BuoyAnalysisData.axis.scaleInverted = d3.scale.linear() BuoyAnalysisChart.axis.scaleInverted = d3.scale.linear()
.domain([BuoyAnalysisData.axis.min, BuoyAnalysisData.axis.max]) .domain([BuoyAnalysisChart.axis.min, BuoyAnalysisChart.axis.max])
.range([0, BuoyAnalysisData.axis.h]); .range([0, BuoyAnalysisChart.axis.h]);
BuoyAnalysisData.axis.fahrenheit = d3.svg.axis() BuoyAnalysisChart.axis.imperial = d3.svg.axis()
.scale(BuoyAnalysisData.axis.scale) .scale(BuoyAnalysisChart.axis.scale)
.orient("left") .orient("left")
.tickFormat(function(d) { return Math.round(d * 9 / 5 + 32); }) .tickFormat(function(d) {
.tickValues([10, 13, 15.5, 18.5, 21]); var val;
BuoyAnalysisData.axis.celsius = d3.svg.axis() switch(BuoyAnalysisChart.bars.property) {
.scale(BuoyAnalysisData.axis.scale) case 'ATMP':
case 'WTMP':
val = Math.round(d * 9 / 5 + 32);
break;
case 'WVHT':
case 'WSPD':
val = Math.round(d * 3.28 * 10) / 10;
break;
case 'WPER':
val = d;
break;
};
return val;
})
.tickValues(tickValues);
BuoyAnalysisChart.axis.metric = d3.svg.axis()
.scale(BuoyAnalysisChart.axis.scale)
.orient("right") .orient("right")
.tickValues([10, 13, 15.5, 18.5, 21]); .tickValues(tickValues);
}, },
/** /**
@ -108,7 +121,7 @@ var BuoyAnalysisData = {
count = 0; count = 0;
stations.forEach(function(id) { stations.forEach(function(id) {
data = BuoyAnalysisData.stationJson[id]['avgs' + year]; data = BuoyAnalysisData.stationJson[id][BuoyAnalysisChart.bars.property + year];
if (data === undefined || data.y === 0) { if (data === undefined || data.y === 0) {
return; return;
@ -137,7 +150,7 @@ var BuoyAnalysisData = {
count = 0; count = 0;
stations.forEach(function(id) { stations.forEach(function(id) {
data = BuoyAnalysisData.stationJson[id]['avgs' + year]; data = BuoyAnalysisData.stationJson[id][BuoyAnalysisChart.bars.property + year];
if (data === undefined || data.m[month] === 0) { if (data === undefined || data.m[month] === 0) {
return; return;

@ -7,7 +7,6 @@
Promise.resolve() Promise.resolve()
.then(BuoyAnalysisData.populateMapData) .then(BuoyAnalysisData.populateMapData)
.then(BuoyAnalysisData.populateSrcFile) .then(BuoyAnalysisData.populateSrcFile)
.then(BuoyAnalysisData.setAxisProperties)
.then(BuoyAnalysisMap.drawMap) .then(BuoyAnalysisMap.drawMap)
.then(BuoyAnalysisMap.drawStations) .then(BuoyAnalysisMap.drawStations)
@ -16,5 +15,6 @@
.then(BuoyAnalysisBehaviors.attachBehaviors) .then(BuoyAnalysisBehaviors.attachBehaviors)
.then(BuoyAnalysisChart.updateAxes)
.then(BuoyAnalysisChart.draw) .then(BuoyAnalysisChart.draw)
})(); })();

@ -0,0 +1,159 @@
* {
box-sizing: border-box;
cursor: default;
font-family: 'open sans';
letter-spacing: 0.7px;
margin: 0;
padding: 0; }
.main {
height: 900px;
margin: 50px auto;
position: relative;
width: 900px; }
#chart {
border: solid #e8e8e8;
border-width: 0 1px;
cursor: pointer;
height: 200px;
left: 0;
position: absolute;
top: 600px;
width: 100%; }
#year-labels {
border: solid #e8e8e8;
border-width: 0 1px 1px 1px;
font-size: 0;
height: 30px;
padding-left: 24px;
position: absolute;
top: 800px;
width: 100%; }
#year-labels .label {
color: #bbb;
cursor: pointer;
display: inline-block;
line-height: 20px;
font-size: 9px;
margin-right: 2px;
text-align: center;
width: 23px; }
.year-toggle:hover {
background: #eee; }
.axis .domain {
fill: none;
stroke: none; }
.axis .tick {
fill: #888;
font-size: 8px; }
.label-axis-y {
fill: #333;
font-size: 10px;
letter-spacing: normal; }
#map {
background: #e8fbfe;
border: 1px solid #e8e8e8;
height: 600px;
position: relative;
width: 100%;
z-index: 0; }
.feature {
fill: #dffbb8;
stroke: #bde484; }
.reticle {
fill: rgba(153, 173, 40, 0.2);
stroke: #5D5336; }
.column-display {
cursor: pointer;
height: 210px;
left: 20px;
overflow: hidden;
position: absolute;
top: 270px;
width: 180px; }
.column-display select {
background: 0;
border: 0;
outline: 0;
width: 200px; }
.column-display .toggle {
background: 0;
color: #ccc;
cursor: pointer;
font-size: 10px;
height: 30px;
letter-spacing: 1.5px;
line-height: 30px;
text-transform: uppercase;
transition: color 0.3s ease; }
.column-display .toggle:hover {
color: #777; }
.column-display .toggle.selected {
color: #444;
cursor: default;
font-weight: bold; }
.reticle-sizer {
left: 20px;
position: absolute;
top: 520px;
z-index: 1; }
.bar-display {
left: 25px;
position: absolute;
top: 560px; }
.bar-display .toggle {
background-image: url("../bar-display.png");
background-repeat: no-repeat;
cursor: pointer;
display: inline-block;
font-size: 0;
height: 40px;
margin-right: 15px;
opacity: 0.15;
transition: opacity 0.3s ease;
width: 30px; }
.bar-display .toggle:hover {
opacity: 1; }
.bar-display .toggle.selected {
cursor: default;
opacity: 1; }
.bar-display .toggle1 {
background-position: -60px 10px; }
.bar-display .toggle2 {
background-position: -30px 10px; }
.bar-display .toggle3 {
background-position: 0 10px; }
input[type=range] {
-webkit-appearance: none; }
input[type=range]::-webkit-slider-runnable-track {
width: 300px;
height: 2px;
background: #ddd;
border: none;
border-radius: 3px; }
input[type=range]::-webkit-slider-thumb {
background: #d8ebd3;
border: 2px solid #5D5336;
border-radius: 50%;
height: 16px;
margin-top: -7px;
width: 16px;
-webkit-appearance: none; }
input[type=range]:focus {
outline: none; }

@ -3,128 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title></title> <title></title>
<link href='https://fonts.googleapis.com/css?family=Indie+Flower' rel='stylesheet' type='text/css'> <link href='css/index.css' rel='stylesheet' type='text/css'>
<style>
* {
box-sizing:border-box;
font-family:'open sans';
letter-spacing:0.7px;
margin: 0;
padding: 0;
}
.main {
height:900px;
margin:50px auto;
position:relative;
width:900px;
}
#map {
background:#e8fbfe;
border:1px solid #e8e8e8;
height:600px;
position:relative;
width:100%;
z-index:0;
}
#chart {
border:solid #e8e8e8;
border-width:0 1px;
cursor:pointer;
height:200px;
left:0;
position:absolute;
top:600px;
width:100%;
}
#year-toggles {
border:solid #e8e8e8;
border-width:0 1px 1px 1px;
font-size:0;
height:30px;
padding-left:24px;
position:absolute;
top:800px;
width:100%;
}
.year-toggle {
border:1px solid #e8e8e8;
color:#bbb;
cursor:pointer;
display:inline-block;
line-height:20px;
font-size:9px;
margin-right:2px;
text-align:center;
width:23px;
}
.year-toggle:hover {
background:#eee;
}
.feature {
fill:#dffbb8;
stroke:#bde484;
}
.reticle {
fill: rgba(153, 173, 40, 0.2);
stroke: #5D5336;
}
.reticle-sizer {
left:10px;
position:absolute;
top:10px;
z-index:1;
}
.axis .domain {
fill: none;
stroke: none;
}
.axis .tick {
fill:#888;
font-size:8px;
}
.label-axis-y {
font-size:10px;
}
input[type=range]{
-webkit-appearance: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 300px;
height: 2px;
background: #ddd;
border: none;
border-radius: 3px;
}
input[type=range]::-webkit-slider-thumb {
background: #d8ebd3;
border: 2px solid #5D5336;
border-radius: 50%;
height: 16px;
margin-top: -7px;
width: 16px;
-webkit-appearance: none;
}
input[type=range]:focus {
outline: none;
}
</style>
</head> </head>
<body> <body>
@ -133,25 +12,32 @@
<input type="range" title='Reticle Size' class='reticle-sizer'> <input type="range" title='Reticle Size' class='reticle-sizer'>
<!-- <div class="container-center"> <div class="bar-display">
<span class="label left">o</span> <div class="toggle toggle1 selected"></div>
<div class="toggle toggle2"></div>
<div class="toggle toggle3"></div>
</div>
<span class="label right">O</span> <div class="column-display">
<div class="toggle toggle1">Air Temperature</div>
<div class="toggle toggle2 selected">Water Temperature</div>
<div class="toggle toggle3">Wave Height</div>
<div class="toggle toggle4">Wave Period</div>
<div class="toggle toggle5">Wind Speed</div>
</div>
<span class="label left">Slow</span> <svg id="chart"></svg>
<input type="range" title='Animation Speed'> <div id="year-labels"></div>
<span class="label fast">Fast</span> </div>
<hr>
<div class="title">Station Data</div> - MAP ocean bottom
- MAP land topography
- MAP mexico and surrounding states
- MAP major major cities
<div class="station-info"></div> - UI reticle sizing
</div> --> - UI reticle drag
<svg id="chart"></svg>
<div id="year-toggles"></div>
</div>
<!-- <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> --> <!-- <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> -->
<script src="d3.min.js"></script> <script src="d3.min.js"></script>

@ -0,0 +1,24 @@
{
"name": "buoy-analysis",
"version": "1.0.0",
"description": "",
"main": "server.js",
"dependencies": {
"chalk": "^1.1.1",
"dateformat": "^1.0.12",
"es6-promise": "^3.0.2",
"node-sass": "^3.4.2",
"watch": "^0.17.1",
"xml2js": "^0.4.15"
},
"devDependencies": {},
"scripts": {
"watch": "node tasks/watch"
},
"repository": {
"type": "git",
"url": "http://gogs.benburlingham.com/ben.burlingham/buoy-analysis"
},
"author": "",
"license": "ISC"
}

Binary file not shown.

@ -0,0 +1,3 @@
NPM scripts task runner:
`npm run watch`

@ -0,0 +1,52 @@
#chart {
border:solid #e8e8e8;
border-width:0 1px;
cursor:pointer;
height:200px;
left:0;
position:absolute;
top:600px;
width:100%;
}
#year-labels {
border:solid #e8e8e8;
border-width:0 1px 1px 1px;
font-size:0;
height:30px;
padding-left:24px;
position:absolute;
top:800px;
width:100%;
.label {
color:#bbb;
cursor:pointer;
display:inline-block;
line-height:20px;
font-size:9px;
margin-right:2px;
text-align:center;
width:23px;
}
}
.year-toggle:hover {
background:#eee;
}
.axis .domain {
fill: none;
stroke: none;
}
.axis .tick {
fill:#888;
font-size:8px;
}
.label-axis-y {
fill: #333;
font-size:10px;
letter-spacing:normal;
}

@ -0,0 +1,22 @@
$mainH: 900px;
$mainW: 900px;
* {
box-sizing:border-box;
cursor:default;
font-family:'open sans';
letter-spacing:0.7px;
margin: 0;
padding: 0;
}
.main {
height:$mainH;
margin:50px auto;
position:relative;
width:$mainW;
}
@import 'chart';
@import 'map';
@import 'options';

@ -0,0 +1,18 @@
#map {
background:#e8fbfe;
border:1px solid #e8e8e8;
height:600px;
position:relative;
width:100%;
z-index:0;
}
.feature {
fill:#dffbb8;
stroke:#bde484;
}
.reticle {
fill: rgba(153, 173, 40, 0.2);
stroke: #5D5336;
}

@ -0,0 +1,116 @@
.column-display {
cursor:pointer;
height:210px;
left:20px;
overflow:hidden;
position:absolute;
top:270px;
width:180px;
select {
background:0;
border:0;
outline:0;
width:200px;
}
.toggle {
background:0;
color:#ccc;
cursor:pointer;
font-size:10px;
height:30px;
letter-spacing:1.5px;
line-height:30px;
text-transform:uppercase;
transition:color 0.3s ease;
&:hover {
color:#777;
}
&.selected {
color:#444;
cursor:default;
font-weight:bold;
}
}
}
.reticle-sizer {
left:20px;
position:absolute;
top:520px;
z-index:1;
}
.bar-display {
$toggleW: 30px;
$toggleH: 40px;
$toggleSpacing: 15px;
left:25px;
position:absolute;
top:560px;
.toggle {
background-image:url('../bar-display.png');
background-repeat:no-repeat;
cursor:pointer;
display:inline-block;
font-size:0;
height:$toggleH;
margin-right:$toggleSpacing;
opacity:0.15;
transition:opacity 0.3s ease;
width:$toggleW;
&:hover {
opacity:1;
}
&.selected {
cursor:default;
opacity:1;
}
}
.toggle1 {
background-position:-60px 10px;
}
.toggle2 {
background-position:-30px 10px;
}
.toggle3 {
background-position:0 10px;
}
}
input[type=range]{
-webkit-appearance: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 300px;
height: 2px;
background: #ddd;
border: none;
border-radius: 3px;
}
input[type=range]::-webkit-slider-thumb {
background: #d8ebd3;
border: 2px solid #5D5336;
border-radius: 50%;
height: 16px;
margin-top: -7px;
width: 16px;
-webkit-appearance: none;
}
input[type=range]:focus {
outline: none;
}

@ -29,11 +29,6 @@ var chalk = require('chalk');
module.exports = { module.exports = {
// Zero indexed column.
// #YY MM DD hh mm WDIR WSPD GST WVHT DPD APD MWD PRES ATMP WTMP DEWP VIS TIDE
// 14 - WTMP (C)
columnToAverage: 14,
/** /**
* *
*/ */
@ -66,7 +61,7 @@ module.exports = {
arr.forEach(function(row) { arr.forEach(function(row) {
val = parseFloat(row[col]); val = parseFloat(row[col]);
if (val === 999 || val === 0) { if (val === 999 || val === 0 || val === 99) {
return; return;
} }
@ -108,7 +103,7 @@ module.exports = {
count = 0; count = 0;
values.map(function(value) { values.map(function(value) {
if (value === 999 || value === 0) { if (value === 999 || value === 0 || value === 99) {
return; return;
} }
@ -125,84 +120,15 @@ module.exports = {
/** /**
* *
*/ */
getDailyAverages: function(arr, col) { getAllMonthlyAverages: function(station, col) {
console.log('Daily averages for column ' + col + '.');
if (arr.length === undefined) {
return [];
}
var sum, count, a, b, doy;
var days = [];
var averages = [];
var dayms = 1000 * 60 * 60 * 24;
for (var i = 0; i <= 365; i++) {
days[i] = [];
}
// Assemble all the values for each day of the year.
arr.forEach(function(row) {
a = new Date(row[0], row[1] - 1, row[2]);
b = new Date(row[0], 0, 1);
doy = Math.ceil((a - b) / dayms);
// if (days[doy] === undefined) {
// // problem here - there are still YYMMDD rows in data
// console.log(row);
// }
days[doy].push(row[col]);
});
// Get the average for each collection of values in each day of the year.
days.forEach(function(values, index) {
sum = 0;
count = 0;
values.map(function(val) {
sum += parseInt(val);
count++;
});
averages[index] = Math.round((sum / count) * 10) / 10 || 0;
});
return averages;
},
/**
*
*/
getAllDailyAverages: function(station, startYear, endYear) {
var result = [];
for (var year = startYear; year <= endYear; year++) {
result.push(
IO.read(meteo.dirs.json + station + '-' + year + '.json')
.then(module.exports.parse)
.then(function(arr) {
return module.exports.getDailyAverages(arr, module.exports.columnToAverage);
})
);
}
return Promise.all(result);
},
/**
*
*/
getAllMonthlyAverages: function(station, startYear, endYear) {
var result = []; var result = [];
for (var year = startYear; year <= endYear; year++) { for (var year = meteo.years.start; year <= meteo.years.end; year++) {
result.push( result.push(
IO.read(meteo.dirs.json + station + '-' + year + '.json') IO.read(meteo.dirs.json + station + '-' + year + '.json')
.then(module.exports.parse) .then(module.exports.parse)
.then(function(arr) { .then(function(arr) {
return module.exports.getMonthlyAverages(arr, module.exports.columnToAverage); return module.exports.getMonthlyAverages(arr, col);
}) })
); );
} }
@ -213,15 +139,15 @@ module.exports = {
/** /**
* *
*/ */
getAllYearlyAverages: function(station, startYear, endYear) { getAllYearlyAverages: function(station, col) {
var result = []; var result = [];
for (var year = startYear; year <= endYear; year++) { for (var year = meteo.years.start; year <= meteo.years.end; year++) {
result.push( result.push(
IO.read(meteo.dirs.json + station + '-' + year + '.json') IO.read(meteo.dirs.json + station + '-' + year + '.json')
.then(module.exports.parse) .then(module.exports.parse)
.then(function(arr) { .then(function(arr) {
return module.exports.getYearlyAverages(arr, module.exports.columnToAverage, station === '46232'); return module.exports.getYearlyAverages(arr, col);
}) })
); );
} }
@ -243,14 +169,11 @@ module.exports = {
*/ */
buildFinalJson: function() { buildFinalJson: function() {
var finalResult = {}; var finalResult = {};
var startYear = 1982;
var endYear = 2015;
function next(index) { function next(index) {
if (index === stations.ids.length) { if (index === stations.ids.length) {
// if (index === 1) { // if (index === 1) {
// IO.write('final-output.json', JSON.stringify(finalResult, null, 4)); // IO.write('_stations.json', JSON.stringify(finalResult, null, 4));
IO.write('_stations.json', JSON.stringify(finalResult)); IO.write('_stations.json', JSON.stringify(finalResult));
return; return;
} }
@ -259,8 +182,12 @@ module.exports = {
// Init objects. // Init objects.
finalResult['s' + station] = {}; finalResult['s' + station] = {};
for (var year = startYear; year <= endYear; year++) { for (var year = meteo.years.start; year <= meteo.years.end; year++) {
finalResult['s' + station]['avgs' + year] = {}; finalResult['s' + station]['WSPD' + year] = {}; // 6
finalResult['s' + station]['WVHT' + year] = {}; // 8
finalResult['s' + station]['WPER' + year] = {}; // 9
finalResult['s' + station]['ATMP' + year] = {}; // 13
finalResult['s' + station]['WTMP' + year] = {}; // 14
} }
Promise.resolve() Promise.resolve()
@ -274,28 +201,83 @@ module.exports = {
finalResult['s' + station].lon = json.lon; finalResult['s' + station].lon = json.lon;
}) })
// Daily // Monthly wind speed
// .then(module.exports.getAllDailyAverages.bind(null, station, startYear, endYear)) .then(module.exports.getAllMonthlyAverages.bind(null, station, 6))
// .then(function(arr) { .then(function(arr) {
// arr.forEach(function(averages, index) { arr.forEach(function(averages, index) {
// finalResult['s' + station]['avgs' + (startYear + index)].d = averages; finalResult['s' + station]['WSPD' + (meteo.years.start + index)].m = averages;
// }); });
// }) })
// Yearly wind speed
.then(module.exports.getAllYearlyAverages.bind(null, station, 6))
.then(function(arr) {
arr.forEach(function(averages, index) {
finalResult['s' + station]['WSPD' + (meteo.years.start + index)].y = averages;
});
})
// Monthly wave height
.then(module.exports.getAllMonthlyAverages.bind(null, station, 8))
.then(function(arr) {
arr.forEach(function(averages, index) {
finalResult['s' + station]['WVHT' + (meteo.years.start + index)].m = averages;
});
})
// Yearly wave height
.then(module.exports.getAllYearlyAverages.bind(null, station, 8))
.then(function(arr) {
arr.forEach(function(averages, index) {
finalResult['s' + station]['WVHT' + (meteo.years.start + index)].y = averages;
});
})
// Monthly wave period
.then(module.exports.getAllMonthlyAverages.bind(null, station, 9))
.then(function(arr) {
arr.forEach(function(averages, index) {
finalResult['s' + station]['WPER' + (meteo.years.start + index)].m = averages;
});
})
// Yearly wave period
.then(module.exports.getAllYearlyAverages.bind(null, station, 9))
.then(function(arr) {
arr.forEach(function(averages, index) {
finalResult['s' + station]['WPER' + (meteo.years.start + index)].y = averages;
});
})
// Monthly air temp
.then(module.exports.getAllMonthlyAverages.bind(null, station, 13))
.then(function(arr) {
arr.forEach(function(averages, index) {
finalResult['s' + station]['ATMP' + (meteo.years.start + index)].m = averages;
});
})
// Yearly air temp
.then(module.exports.getAllYearlyAverages.bind(null, station, 13))
.then(function(arr) {
arr.forEach(function(averages, index) {
finalResult['s' + station]['ATMP' + (meteo.years.start + index)].y = averages;
});
})
// Monthly // Monthly water temp
.then(module.exports.getAllMonthlyAverages.bind(null, station, startYear, endYear)) .then(module.exports.getAllMonthlyAverages.bind(null, station, 14))
.then(function(arr) { .then(function(arr) {
arr.forEach(function(averages, index) { arr.forEach(function(averages, index) {
finalResult['s' + station]['avgs' + (startYear + index)].m = averages; finalResult['s' + station]['WTMP' + (meteo.years.start + index)].m = averages;
}); });
}) })
// Yearly // Yearly water temp
.then(module.exports.getAllYearlyAverages.bind(null, station, startYear, endYear)) .then(module.exports.getAllYearlyAverages.bind(null, station, 14))
.then(function(arr) { .then(function(arr) {
arr.forEach(function(averages, index) { arr.forEach(function(averages, index) {
finalResult['s' + station]['avgs' + (startYear + index)].y = averages; finalResult['s' + station]['WTMP' + (meteo.years.start + index)].y = averages;
}); });
}) })

@ -15,6 +15,11 @@ module.exports = {
months: [null, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], months: [null, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
years: {
start: 1982,
end: 2015
},
//========================== //==========================
// Downloads // Downloads
//========================== //==========================

@ -0,0 +1,21 @@
var sass = require('node-sass');
var fs = require('fs');
var chalk = require('chalk');
var dateFormat = require('dateformat');
function thenWrite(err, result) {
if (err) {
console.log(err);
return;
}
var d = new Date();
fs.writeFile('css/index.css', result.css, 'utf8');
console.log(dateFormat(new Date(), "dddd mmm d H:MM:ss") + ' ' + chalk.green('Rendered css/index.css'))
}
module.exports = {
render: function() {
sass.render({ file: 'sass/index.scss' }, thenWrite);
}
}

@ -0,0 +1,11 @@
var watch = require('watch');
var sass = require('./sass');
watch.watchTree('sass', function (f, curr, prev) {
if (typeof f == "object" && prev === null && curr === null) {
// Finished walking the tree
return;
}
sass.render();
});
Loading…
Cancel
Save