Skip to content

Commit

Permalink
w/ co2 api
Browse files Browse the repository at this point in the history
  • Loading branch information
corradio committed Sep 15, 2016
0 parents commit 9b89e8a
Show file tree
Hide file tree
Showing 535 changed files with 39,408 additions and 0 deletions.
27 changes: 27 additions & 0 deletions app/browsercheck.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
function isChrome() {
// Snippet taken from: http://stackoverflow.com/questions/4565112/javascript-how-to-find-out-if-the-user-browser-is-chrome/13348618#13348618
//
// please note
// that IE11 now returns undefined again for window.chrome
// and new Opera 30 outputs true for window.chrome
// and new IE Edge outputs to true now for window.chrome
// and if not iOS Chrome check
// so use the below updated condition
var isChromium = window.chrome,
winNav = window.navigator,
vendorName = winNav.vendor,
isOpera = winNav.userAgent.indexOf("OPR") > -1,
isIEedge = winNav.userAgent.indexOf("Edge") > -1,
isIOSChrome = winNav.userAgent.match("CriOS");

if (isIOSChrome) {
// is Google Chrome on IOS
return true;
} else if (isChromium !== null && isChromium !== undefined && vendorName === "Google Inc." && isOpera == false && isIEedge == false) {
// is Google Chrome
return true;
} else {
// not Google Chrome
return false;
}
}
115 changes: 115 additions & 0 deletions app/co2eq.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
function Co2eqCalculator() {
// Node dependencies
if (typeof require != 'undefined') {
d3 = require('d3');
math = require('mathjs');
}

this.defaultCo2eqFootprint = {
'biomass': 740,
'coal': 820,
'gas': 490,
'hydro': 24,
'nuclear': 12,
'oil': 650,
'solar': 45,
'wind': 12,
}; // in gCo2eq/kWh

this.countryCo2eqFootprint = {
'DE': function (productionMode) {
return productionMode == 'other' ? 700 : null;
},
'DK': function (productionMode) {
return productionMode == 'other' ? 700 : null;
},
'FI': function (productionMode) {
return productionMode == 'other' ? 700 : null;
},
'GB': function (productionMode) {
return productionMode == 'other' ? 300 : null;
},
'NO': function (productionMode) {
return productionMode == 'other' ? 700 : null;
},
'SE': function (productionMode) {
return productionMode == 'other' ? 700 : null;
}
};

this.footprintOf = function(productionMode, countryKey) {
var defaultFootprint = this.defaultCo2eqFootprint[productionMode];
var countryFootprint = this.countryCo2eqFootprint[countryKey] || function () { };
return countryFootprint(productionMode) || defaultFootprint;
};

this.compute = function(countries) {
var validCountries = d3.entries(countries)
.map(function(d) { return d.value.data })
.filter(function (d) {
return d.countryCode !== undefined;
});
var validCountryKeys = validCountries.map(function (d) { return d.countryCode });

// x_i: unknown co2 (consumption) footprint of i-th country
// f_ij: known co2 footprint of j-th system of i-th country
// v_ij: power volume of j-th system of i-th country
// CO2 mass flow balance equation for each country i:
// x_i * (sum_j_intern(v_ij) + sum_j_import(v_ij) - sum_j_export(v_ij)) =
// sum_j_intern(f_ij * v_ij)
// + sum_j_import(x_j * v_ij)
// - x_i * sum_j_export(v_ij)

// We wish to solve Ax = b
var n = validCountries.length;
var A = math.sparse().resize([n, n]);
var b = math.zeros(n);

var that = this;

validCountries.forEach(function (country, i) {
A.set([i, i], -country.totalProduction - country.totalNetExchange);
// Intern
d3.entries(country.production).forEach(function (production) {
var footprint = that.footprintOf(production.key, country.countryCode);
if (footprint === undefined) {
console.warn(country.countryCode + ' CO2 footprint of ' + production.key + ' is unknown');
return;
}
// Accumulate
b.set([i], b.get([i]) - footprint * production.value);
});
// Exchanges
d3.entries(country.exchange).forEach(function (exchange) {
var j = validCountryKeys.indexOf(exchange.key);
if (j < 0) {
console.warn(country.countryCode + ' neighbor ' + exchange.key + ' has no data');
return;
}
if (exchange.value > 0) {
// Import
A.set([i, j], exchange.value);
} else {
// Accumulate export
A.set([i, i], A.get([i, i]) - Math.abs(exchange.value));
}
});
});

// Solve
var x = math.lusolve(A, b);
this.assignments = {};
x.toArray().forEach(function (x, i) {
that.assignments[validCountries[i].countryCode] = x[0];
});

return this;
}

return this;
}

if (typeof module != 'undefined')
module.exports = {
Co2eqCalculator: Co2eqCalculator
}
119 changes: 119 additions & 0 deletions app/countrymap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
function CountryMap(selector, co2color) {
var that = this;

this.STROKE_WIDTH = 0.3;

this.selectedCountry = undefined;

this.root = d3.select(selector);
this.co2color = co2color;
this.graticule = this.root
.on('click', function (d, i) {
if (that.selectedCountry !== undefined) {
that.selectedCountry
.style('stroke', 'black')
.style('stroke-width', that.STROKE_WIDTH);
}
that.seaClickHandler.call(this, d, i);
})
.append('path')
.attr('class', 'graticule')
this.land = this.root.append('g');
}

CountryMap.prototype.render = function() {
var computedMapWidth = this.root.node().getBoundingClientRect().width,
computedMapHeight = this.root.node().getBoundingClientRect().height;

this._projection = d3.geo.mercator()
.center([3, 48])
.translate([0.6 * computedMapWidth, 0.6 * computedMapHeight])
.scale(700);

this.path = d3.geo.path()
.projection(this._projection);

var graticuleData = d3.geo.graticule()
.step([5, 5]);

this.graticule
.datum(graticuleData)
.attr('d', this.path);

var that = this;
if (this._data) {
var getCo2Color = function (d) {
return (d.data.co2 !== undefined) ? that.co2color(d.data.co2) : 'gray';
};
var selector = this.land.selectAll('.country')
.data(this._data);
selector.enter()
.append('path')
.attr('class', 'country')
.attr('stroke', 'black')
.attr('stroke-width', that.STROKE_WIDTH)
.attr('fill', getCo2Color)
.on('mouseover', function (d, i) {
return that.countryMouseOverHandler.call(this, d, i);
})
.on('mouseout', function (d, i) {
return that.countryMouseOutHandler.call(this, d, i);
})
.on('click', function (d, i) {
d3.event.stopPropagation(); // To avoid call click on sea
if (that.selectedCountry !== undefined) {
that.selectedCountry
.style('stroke', 'black')
.style('stroke-width', that.STROKE_WIDTH);
}
that.selectedCountry = d3.select(this);
// that.selectedCountry
// .style('stroke', 'darkred')
// .style('stroke-width', 1.5);
return that.countryClickHandler.call(this, d, i);
});
selector
.attr('d', this.path)
.transition()
.attr('fill', getCo2Color);
}
}

CountryMap.prototype.projection = function(arg) {
if (!arg) return this._projection;
else this._projection = arg;
return this;
};

CountryMap.prototype.onSeaClick = function(arg) {
if (!arg) return this.seaClickHandler;
else this.seaClickHandler = arg;
return this;
};

CountryMap.prototype.onCountryClick = function(arg) {
if (!arg) return this.countryClickHandler;
else this.countryClickHandler = arg;
return this;
};

CountryMap.prototype.onCountryMouseOver = function(arg) {
if (!arg) return this.countryMouseOverHandler;
else this.countryMouseOverHandler = arg;
return this;
};

CountryMap.prototype.onCountryMouseOut = function(arg) {
if (!arg) return this.countryMouseOutHandler;
else this.countryMouseOutHandler = arg;
return this;
};

CountryMap.prototype.data = function(data) {
if (!data) {
return this._data;
} else {
this._data = data;
}
return this;
};
Loading

0 comments on commit 9b89e8a

Please sign in to comment.