-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
220 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
module.exports = { | ||
instanceConfig: function(opts) { | ||
return function (req, res, next) { | ||
var start = Date.now(), | ||
hasInstance = !!req.query.instance_id; | ||
if (!hasInstance) { | ||
// If we don't have an instance_id (e.g. a health-check request) | ||
// skip this middleware. | ||
next(); | ||
return; | ||
} | ||
req.instanceConfig = {}; | ||
opts.dbPool.connect(function(err, client, done) { | ||
if (!err) { | ||
var instanceId = parseInt(req.query.instance_id, 10); | ||
client.query('SELECT config FROM treemap_instance WHERE id = $1', | ||
[instanceId], function(err, result) { | ||
if (!err && result && result.rows && result.rows.length > 0) { | ||
req.instanceConfig = JSON.parse(result.rows[0].config); | ||
} | ||
done(); | ||
if (opts.debug) { | ||
console.log('[instanceConfig] query time ' + (Date.now() - start)); | ||
} | ||
next(err); | ||
}); | ||
} else { | ||
done(); | ||
if (opts.debug) { | ||
console.log('[instanceConfig] query time ' + (Date.now() - start)); | ||
} | ||
next(err); | ||
} | ||
}); | ||
}; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
"use strict"; | ||
|
||
var assert = require("assert"); | ||
var _ = require("underscore"); | ||
var units = require("../units"); | ||
var config = require("../config"); | ||
|
||
describe('convertFilterUnits', function() { | ||
var round = function(number, precision) { | ||
var factor = Math.pow(10, precision); | ||
var tempNumber = number * factor; | ||
var roundedTempNumber = Math.round(tempNumber); | ||
return roundedTempNumber / factor; | ||
}; | ||
|
||
it('exists', function() { | ||
assert.ok(_.isFunction(units.convertFilterUnits), | ||
'convertFilterUnits function should exist'); | ||
}); | ||
|
||
it('ignores non-convertible fields', function(){ | ||
var filter = {'tree.something': {'IS': 'some value'}}; | ||
var config = {value_display: {tree: {diameter: {'units': 'in'}}}}; | ||
var expectedFilter = _.clone(filter); | ||
units.convertFilterUnits(filter, config); | ||
assert.deepEqual(filter, expectedFilter, 'Filter should not change'); | ||
}); | ||
|
||
it('does not change a value with default unit', function(){ | ||
var filter = {'tree.diameter': {'MIN': 1, 'MAX': 2}}; | ||
var config = {value_display: {tree: {diameter: {'units': 'in'}}}}; | ||
var expectedFilter = _.clone(filter); | ||
units.convertFilterUnits(filter, config); | ||
assert.deepEqual(filter, expectedFilter, 'Filter should not change'); | ||
}); | ||
|
||
it('converts min and max diameter filter', function(){ | ||
var filter = {'tree.diameter': {'MIN': 1, 'MAX': 2}}; | ||
var config = {value_display: {tree: {diameter: {'units': 'cm'}}}}; | ||
var expectedFilter = {'tree.diameter': {'MIN': 0.393701, 'MAX': 0.787402}}; | ||
units.convertFilterUnits(filter, config); | ||
// Round before asserting because the actual conversion to compare floats with a known level of precision | ||
filter['tree.diameter'].MIN = round(filter['tree.diameter'].MIN, 6); | ||
filter['tree.diameter'].MAX = round(filter['tree.diameter'].MAX, 6); | ||
assert.deepEqual(filter, expectedFilter, 'Filter should show cm->in conversion'); | ||
}); | ||
|
||
it('converts min and max filter with alternate syntax', function(){ | ||
var filter = {'tree.diameter': {'MIN': {'VALUE': 1}, 'MAX': {'VALUE': 2}}}; | ||
var config = {value_display: {tree: {diameter: {'units': 'cm'}}}}; | ||
var expectedFilter = {'tree.diameter': {'MIN': {'VALUE': 0.393701}, 'MAX': {'VALUE': 0.787402}}}; | ||
units.convertFilterUnits(filter, config); | ||
// Round before asserting because the actual conversion to compare floats with a known level of precision | ||
filter['tree.diameter'].MIN.VALUE = round(filter['tree.diameter'].MIN.VALUE, 6); | ||
filter['tree.diameter'].MAX.VALUE = round(filter['tree.diameter'].MAX.VALUE, 6); | ||
assert.deepEqual(filter, expectedFilter, 'Filter should show cm->in conversion'); | ||
}); | ||
|
||
it('converts min and max bioswale filter', function(){ | ||
var filter = {'bioswale.drainage_area': {'MIN': 1, 'MAX': 2}}; | ||
var config = {value_display: {bioswale: {drainage_area: {'units': 'sq_m'}}}}; | ||
var expectedFilter = {'bioswale.drainage_area': {'MIN': 10.7643, 'MAX': 21.5285}}; | ||
units.convertFilterUnits(filter, config); | ||
// Round before asserting because the actual conversion to compare floats with a known level of precision | ||
filter['bioswale.drainage_area'].MIN = round(filter['bioswale.drainage_area'].MIN, 4); | ||
filter['bioswale.drainage_area'].MAX = round(filter['bioswale.drainage_area'].MAX, 4); | ||
assert.deepEqual(filter, expectedFilter, 'Filter should show sq_ft->sq_m conversion'); | ||
}); | ||
|
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
"use strict"; | ||
|
||
var _ = require("underscore"); | ||
|
||
var convertableFields = ['tree.diameter', 'tree.height', 'tree.canopy_height', | ||
'plot.width', 'plot.length', 'bioswale.drainage_area', | ||
'rainBarrel.capacity', 'rainGarden.drainage_area']; | ||
|
||
var unitDefaults = { | ||
plot: { | ||
width: 'in', | ||
length: 'in' | ||
}, | ||
tree: { | ||
diameter: 'in', | ||
height: 'ft', | ||
canopy_height: 'ft' | ||
}, | ||
bioswale: { | ||
drainage_area: 'sq_ft' | ||
}, | ||
rainBarrel: { | ||
capacity: 'gal' | ||
}, | ||
rainGarden: { | ||
drainage_area: 'sq_ft' | ||
} | ||
}; | ||
|
||
var unitConversions = { | ||
'in': {'in': 1, 'ft': 1 / 12, 'cm': 2.54, 'm': 0.0254}, | ||
'ft': {'in': 12, 'ft': 1, 'cm': 30.48, 'm': 0.3048}, | ||
'lbs/year': {'lbs/year': 1, 'kg/year': 0.453592}, | ||
'lbs': {'lbs': 1, 'kg': 0.453592}, | ||
'gal': {'gal': 1, 'L': 3.785}, | ||
'gal/year': {'gal/year': 1, 'L/year': 3.785}, | ||
'kwh/year': {'kwh/year': 1}, | ||
'sq_m': {'sq_m': 1, 'sq_ft': 10.7639}, | ||
'sq_ft': {'sq_m': 0.0929, 'sq_ft': 1} | ||
}; | ||
|
||
function getFilterFactor(instanceConfig, model, field) { | ||
var unit, defaultUnit, | ||
factor = 1; | ||
if (instanceConfig.value_display[model]) { | ||
if (instanceConfig.value_display[model][field]) { | ||
unit = instanceConfig.value_display[model][field].units; | ||
defaultUnit = unitDefaults[model][field]; | ||
factor = 1 / unitConversions[defaultUnit][unit]; | ||
} | ||
} | ||
return factor; | ||
} | ||
|
||
function convertFilterValue(value, factor) { | ||
if (_.isObject(value)) { | ||
_.each(['MIN', 'MAX', 'IS'], function(k) { | ||
var floatValue; | ||
if (value[k]) { | ||
if (_.isObject(value[k])) { | ||
floatValue = parseFloat(value[k].VALUE); | ||
if (_.isNumber(floatValue)) { | ||
value[k].VALUE = floatValue * factor; | ||
} | ||
} else { | ||
floatValue = parseFloat(value[k]); | ||
if (_.isNumber(floatValue)) { | ||
value[k] = floatValue * factor; | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
return value; | ||
} | ||
|
||
function convertFilterUnits(filterObject, instanceConfig) { | ||
// if there is no unit configuration, there is no need to convert | ||
if (instanceConfig && instanceConfig.value_display) { | ||
_.each(_.keys(filterObject), function(fieldName) { | ||
var value = filterObject[fieldName]; | ||
if (_.contains(convertableFields, fieldName)) { | ||
var model = fieldName.split('.')[0], | ||
field = fieldName.substring(fieldName.indexOf('.') + 1), | ||
factor = getFilterFactor(instanceConfig, model, field); | ||
convertFilterValue(value, factor); | ||
} | ||
}); | ||
} | ||
return filterObject; | ||
} | ||
|
||
exports = module.exports = { | ||
convertFilterUnits: convertFilterUnits | ||
}; |