From: Lunar Date: Sat, 23 Nov 2013 16:41:51 +0000 (+0100) Subject: Proprification et mise en place des graphs X-Git-Url: https://nos-oignons.net/gitweb/website.git/commitdiff_plain/8432d2f44740eaccd47c14abe52b1df01f5bb6d6 Proprification et mise en place des graphs --- diff --git a/README b/README index 44cdc40..089fb03 100644 --- a/README +++ b/README @@ -49,3 +49,10 @@ Images Les sources des images utilisés se trouve dans le répertoire `Site_web` du dépôt « comm ». + +Modification de la liste des relais +----------------------------------- + +La liste des relais gérés par Nos oignons se trouve à deux endroits : +`Services.mdwn` et `assets/relays.js`. Il faut bien penser à tout mettre à +jour. diff --git a/Services.en.po b/Services.en.po index ba68054..3d0d655 100644 --- a/Services.en.po +++ b/Services.en.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: Nos oignons website\n" -"POT-Creation-Date: 2013-11-17 15:40+0100\n" -"PO-Revision-Date: 2013-11-17 16:00+0100\n" +"POT-Creation-Date: 2013-11-23 19:39+0100\n" +"PO-Revision-Date: 2013-11-23 19:50+0100\n" "Last-Translator: Nos oignons \n" "Language-Team: English \n" "Language: en\n" @@ -10,11 +10,137 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +#. type: Plain text +#, no-wrap +msgid "[[!meta script=\"assets/l10n.fr\"]]\n" +msgstr "[[!meta script=\"assets/l10n.en\"]]\n" + +#. type: Plain text +#, no-wrap +msgid "[[!meta script=\"assets/relays\"]]\n" +msgstr "[[!meta script=\"assets/relays\"]]\n" + +#. type: Plain text +#, no-wrap +msgid "[[!meta script=\"assets/d3/d3.v3.min\"]]\n" +msgstr "[[!meta script=\"assets/d3/d3.v3.min\"]]\n" + +#. type: Plain text +#, no-wrap +msgid "[[!meta script=\"assets/bw_graphs\"]]\n" +msgstr "[[!meta script=\"assets/bw_graphs\"]]\n" + +#. type: Plain text +#, no-wrap +msgid "[[!meta stylesheet=\"assets/bw_graphs\" rel=\"stylesheet\"]]\n" +msgstr "[[!meta stylesheet=\"assets/bw_graphs\" rel=\"stylesheet\"]]\n" + +#. type: Plain text +#, no-wrap +msgid "[[!meta script=\"assets/pie_graphs\"]]\n" +msgstr "[[!meta script=\"assets/pie_graphs\"]]\n" + #. type: Plain text #, no-wrap msgid "[[!meta title=\"Services\"]]\n" msgstr "[[!meta title=\"Services\"]]\n" +#. type: Plain text +#, no-wrap +msgid "\n" +msgstr "" +"new ConsensusPieDrawer(\"#consensus-pie\").draw();\n" +"new ExitPieDrawer(\"#exit-pie\").draw();\n" +"\n" + +#. type: Title = +#, no-wrap +msgid "Relais\n" +msgstr "Relays\n" + #. type: Plain text msgid "Nos oignons fait actuellement fonctionner les relais Tor suivants :" msgstr "Nos Oignons currently runs the following Tor relays:" @@ -114,3 +240,29 @@ msgstr "" " \n" " \n" "\n" + +#. type: Plain text +#, no-wrap +msgid "" +"\n" +msgstr "" +"new BwDrawer(\"#bandwidth\").draw();\n" +"\n" diff --git a/Services.mdwn b/Services.mdwn index 084f720..88bb60c 100644 --- a/Services.mdwn +++ b/Services.mdwn @@ -1,5 +1,53 @@ +[[!meta script="assets/l10n.fr"]] +[[!meta script="assets/relays"]] +[[!meta script="assets/d3/d3.v3.min"]] +[[!meta script="assets/bw_graphs"]] +[[!meta stylesheet="assets/bw_graphs" rel="stylesheet"]] +[[!meta script="assets/pie_graphs"]] [[!meta title="Services"]] + + +Relais +====== + Nos oignons fait actuellement fonctionner les relais Tor suivants : @@ -48,3 +96,13 @@ Nos oignons fait actuellement fonctionner les relais Tor suivants :
+ + diff --git a/Services/Participation.html b/Services/Participation.html deleted file mode 100644 index e3edb65..0000000 --- a/Services/Participation.html +++ /dev/null @@ -1,328 +0,0 @@ -[[!meta script="assets/relays"]] -[[!meta script="assets/d3/d3.v3.min"]] - - - -
-

Consensus weight

-
-
-
-

Exit probability

-
-
-
- - - -

Bandwidth

- -

3 days / read

-
-

3 days / write

-
-

1 week / read

-
-

1 week / write

-
-

1 month / read

-
-

1 month / write

-
-

3 months / read

-
-

3 months / write

-
-

1 year / read

-
-

1 year / write

-
- - - - diff --git a/assets/bw_graphs.css b/assets/bw_graphs.css new file mode 100644 index 0000000..a455147 --- /dev/null +++ b/assets/bw_graphs.css @@ -0,0 +1,19 @@ +.axis path, +.axis line { + fill: none; + stroke: #000; + shape-rendering: crispEdges; +} + +#bandwidth form { + margin: auto; + width: 35em; +} + +#bandwidth div { + float: left; + width: 7em; +} +#bandwidth svg { + clear: left; +} diff --git a/assets/bw_graphs.js b/assets/bw_graphs.js new file mode 100644 index 0000000..bcd0216 --- /dev/null +++ b/assets/bw_graphs.js @@ -0,0 +1,224 @@ +function BwDrawer(selector) { + this.selector = selector; +}; +BwDrawer.prototype = new BwDrawer(); + +BwDrawer.margin = {top: 50, right: 10, bottom: 90, left: 130}; +BwDrawer.width = 600 - BwDrawer.margin.left - BwDrawer.margin.right; +BwDrawer.height = 400 - BwDrawer.margin.top - BwDrawer.margin.bottom; + +BwDrawer.parseTime = d3.time.format("%Y-%m-%d %H:%M:%S").parse; +BwDrawer.bwFormatter = d3.format(".f"); + +BwDrawer.x = d3.time.scale() + .range([0, BwDrawer.width]); + +BwDrawer.y = d3.scale.linear() + .range([BwDrawer.height, 0]); + +BwDrawer.color = d3.scale.category20(); + +BwDrawer.xAxis = d3.svg.axis() + .scale(BwDrawer.x) + .orient("bottom"); + +BwDrawer.yAxis = d3.svg.axis() + .scale(BwDrawer.y) + .orient("left") + .tickFormat(function(d) { return (d == 0) ? "" : BwDrawer.bwFormatter(Math.abs(d)) + " Mbit/s " + ((d > 0) ? "in" : "out"); }); + +BwDrawer.area = d3.svg.area() + .x(function(d) { return BwDrawer.x(d.date); }) + .y0(function(d) { return BwDrawer.y(d.y0); }) + .y1(function(d) { return BwDrawer.y(d.y0 + d.y); }); + +BwDrawer.read_stack = d3.layout.stack() + .values(function(d) { return d.read_values; }); +BwDrawer.write_stack = d3.layout.stack() + .values(function(d) { return d.write_values; }); + +BwDrawer.onionoo_url = "https://onionoo.torproject.org/bandwidth?type=relay&contact=adminsys@nos-oignons.net"; + +BwDrawer.periods = [ + { id: "3_days", label: L10n.t_3_days }, + { id: "1_week", label: L10n.t_1_week }, + { id: "1_month", label: L10n.t_1_month }, + { id: "3_months", label: L10n.t_3_months }, + { id: "1_year", label: L10n.t_1_year }, + ]; + +BwDrawer.extract_values = function(history, interval, minTime, maxTime) { + var values = []; + var first = history ? BwDrawer.parseTime(history.first) : maxTime; + var last = history ? BwDrawer.parseTime(history.last) : minTime; + var i = 0; + for (var current = minTime; current <= maxTime; current = d3.time.second.offset(current, interval)) { + values.push({ date: current, + y: (first <= current && current <= last) ? history.factor * history.values[i++] * 8 / 1000000 : 0 + }); + } + return values; +} + +BwDrawer.draw_bandwidth_graph = function(raw_data, selector, period) { + var update_period; + + var svg = d3.select(selector).append("svg") + .attr("width", BwDrawer.width + BwDrawer.margin.left + BwDrawer.margin.right) + .attr("height", BwDrawer.height + BwDrawer.margin.top + BwDrawer.margin.bottom) + .append("g") + .attr("transform", "translate(" + BwDrawer.margin.left + "," + BwDrawer.margin.top + ")"); + + var form = d3.select(selector).append("form") + .attr("action", "#"); + BwDrawer.periods.forEach(function(p) { + var div = form.append("div"); + var radio = div.append("input") + .attr("type", "radio") + .attr("name", "period") + .attr("id", "period_" + p.id) + .on("click", function() { update_period(p.id); }); + div.append("label") + .attr("for", "period_" + p.id) + .text(p.label); + if (p.id == BwDrawer.periods[0].id) { + radio.attr("checked", true); + } + }); + + var valid_fingerprints = []; + nos_oignons_relays.forEach(function(r) { + var relay_data = raw_data["relays"].filter(function(d) { return d.fingerprint == r.fingerprint; })[0]; + valid_fingerprints.push(r.fingerprint); + }); + BwDrawer.color.domain(valid_fingerprints); + + var bw_data = {}; + BwDrawer.periods.map(function(p) { return p.id; }).forEach(function(period) { + var interval = d3.max(raw_data.relays, function(d) { + return d['read_history'][period] && d['read_history'][period].interval; + }); + raw_data.relays.forEach(function(d) { + if ((d['read_history'][period] && d['read_history'][period].interval != interval) || + (d['write_history'][period] && d['write_history'][period].interval != interval)) { + throw "PANIC: Different interval for different relays in the same time period."; + } + }); + var minTime = d3.max(raw_data.relays, function(d) { + return d['read_history'][period] && BwDrawer.parseTime(d['read_history'][period].first) && + d['write_history'][period] && BwDrawer.parseTime(d['write_history'][period].first); + }); + var maxTime = d3.min(raw_data.relays, function(d) { + return d['read_history'][period] && BwDrawer.parseTime(d['read_history'][period].last) && + d['write_history'][period] && BwDrawer.parseTime(d['write_history'][period].last); + }); + + var maxReadBandwidth = 0; + var maxWriteBandwidth = 0; + + var values = BwDrawer.color.domain().map(function(fingerprint) { + var relay_data = raw_data["relays"].filter(function(d) { return d.fingerprint == fingerprint; })[0]; + var read_history = relay_data['read_history'][period]; + var write_history = relay_data['write_history'][period]; + var read_values = BwDrawer.extract_values(read_history, interval, minTime, maxTime); + var write_values = BwDrawer.extract_values(write_history, interval, minTime, maxTime); + + maxReadBandwidth = maxReadBandwidth + d3.max(read_values, function(d) { return d.y; }); + maxWriteBandwidth = maxWriteBandwidth + d3.max(write_values, function(d) { return d.y; }); + + return { + fingerprint: fingerprint, + read_values: read_values, + write_values: write_values.map(function(d) { d.y = -d.y; return d }) + }; + }); + bw_data[period] = { minTime: minTime, + maxTime: maxTime, + maxReadBandwidth: maxReadBandwidth, + maxWriteBandwidth: maxWriteBandwidth, + values: values }; + }); + + BwDrawer.y.domain([-d3.max(d3.values(bw_data), function(d) { return d.maxWriteBandwidth; }), + d3.max(d3.values(bw_data), function(d) { return d.maxReadBandwidth; })]); + + var initial_period = BwDrawer.periods[0].id; + + BwDrawer.x.domain([bw_data[initial_period].minTime, bw_data[initial_period].maxTime]); + + var read_graph = svg.selectAll(".read_graph") + .data(BwDrawer.read_stack(bw_data[initial_period].values)) + .enter().append("path") + .attr("class", "read_graph area") + .attr("d", function(d) { return BwDrawer.area(d.read_values); }) + .style("fill", function(d) { return BwDrawer.color(d.fingerprint); }); + + var write_graph = svg.selectAll(".write_graph") + .data(BwDrawer.write_stack(bw_data[initial_period].values)) + .enter().append("path") + .attr("class", "write_graph area") + .attr("d", function(d) { return BwDrawer.area(d.write_values); }) + .style("fill", function(d) { return BwDrawer.color(d.fingerprint); }); + + update_period = function(period) { + BwDrawer.x.domain([bw_data[period].minTime, bw_data[period].maxTime]); + var t = svg.transition().duration(300); + t.select(".x.axis").call(BwDrawer.xAxis); + t.selectAll(".read_graph").style("fill-opacity", 0); + t.selectAll(".write_graph").style("fill-opacity", 0); + t.each("end", function() { + d3.selectAll(".read_graph").data(BwDrawer.read_stack(bw_data[period].values)); + d3.selectAll(".write_graph").data(BwDrawer.write_stack(bw_data[period].values)); + d3.selectAll(".read_graph").attr("d", function(d) { return BwDrawer.area(d.read_values); }) + d3.selectAll(".write_graph") + .attr("d", function(d) { return BwDrawer.area(d.write_values); }) + var t2 = svg.transition().duration(100); + t2.selectAll(".read_graph").style("fill-opacity", 1); + t2.selectAll(".write_graph").style("fill-opacity", 1); + }); + d3.selectAll(".x.axis text") + .style("text-anchor", "end") + .attr("transform", "rotate(-90) translate(-10, 0)"); + } + + svg.append("g") + .attr("class", "x axis") + .attr("transform", "translate(0," + BwDrawer.height + ")") + .call(BwDrawer.xAxis) + .selectAll("text") + .style("text-anchor", "end") + .attr("transform", "rotate(-90) translate(-10, 0)"); + + svg.append("g") + .attr("class", "y axis") + .call(BwDrawer.yAxis); + + var legend = svg.selectAll(".legend") + .data(BwDrawer.color.domain().slice().reverse()) + .enter().append("g") + .attr("class", "legend") + .attr("transform", function(d, i) { return "translate(0," + ((i * 20) - BwDrawer.margin.top) + ")"; }); + + legend.append("rect") + .attr("x", BwDrawer.width - 18) + .attr("width", 18) + .attr("height", 18) + .style("fill", BwDrawer.color); + + legend.append("text") + .attr("x", BwDrawer.width - 24) + .attr("y", 9) + .attr("dy", ".35em") + .style("text-anchor", "end") + .text(function(d) { + return nos_oignons_relays.filter(function(r) { return r.fingerprint == d; })[0].name; + }); +}; + +BwDrawer.prototype.draw = function() { + var selector = this.selector; + d3.json(BwDrawer.onionoo_url, function(error, raw_data) { + d3.select(selector).text(""); + BwDrawer.draw_bandwidth_graph(raw_data, selector); + }); +}; diff --git a/assets/l10n.en.js b/assets/l10n.en.js new file mode 100644 index 0000000..f89d7a5 --- /dev/null +++ b/assets/l10n.en.js @@ -0,0 +1,12 @@ +function L10n() { }; +L10n.loading = "Loading…"; +L10n.consensus_weight = "Weight in the whole network"; +L10n.exit_probability = "Probability to be used as exit node"; +L10n.bandwidth = "Bandwidth"; +L10n.nos_oignons = "Nos oignons"; +L10n.others = "Others"; +L10n.t_3_days = "3 days"; +L10n.t_1_week = "1 week"; +L10n.t_1_month = "1 month"; +L10n.t_3_months = "3 months"; +L10n.t_1_year = "1 year"; diff --git a/assets/l10n.fr.js b/assets/l10n.fr.js new file mode 100644 index 0000000..0e948d5 --- /dev/null +++ b/assets/l10n.fr.js @@ -0,0 +1,12 @@ +function L10n() { }; +L10n.loading = "Chargement…"; +L10n.consensus_weight = "Poid dans l'ensemble du réseau"; +L10n.exit_probability = "Probabilité d'être utilisé comme nœud de sortie"; +L10n.bandwidth = "Bande passante"; +L10n.nos_oignons = "Nos oignons"; +L10n.others = "Autres"; +L10n.t_3_days = "3 jours"; +L10n.t_1_week = "1 semaine"; +L10n.t_1_month = "1 mois"; +L10n.t_3_months = "3 mois"; +L10n.t_1_year = "1 an"; diff --git a/assets/pie_graphs.js b/assets/pie_graphs.js new file mode 100644 index 0000000..e607fa5 --- /dev/null +++ b/assets/pie_graphs.js @@ -0,0 +1,94 @@ +function PieDrawer(selector) { + this.selector = selector; +}; +PieDrawer.width = 150; +PieDrawer.height = 150; +PieDrawer.radius = Math.min(PieDrawer.width, PieDrawer.height) / 2; +PieDrawer.formatPercent = d3.format(".2%"); + +PieDrawer.color_nos_oignons = "#ffa430"; +PieDrawer.color_others = "#57075f"; + +PieDrawer.arc = d3.svg.arc() + .outerRadius(PieDrawer.radius - 10) + .innerRadius(PieDrawer.radius - 40); + +PieDrawer.labelRadius = PieDrawer.radius - 15; + +PieDrawer.pie = d3.layout.pie() + .sort(null) + .value(function(d) { return d.frac; }); + +PieDrawer.onionoo_url = "https://onionoo.torproject.org/details?type=relay&contact=adminsys@nos-oignons.net"; + +PieDrawer.prototype.getFieldName = undefined; +PieDrawer.prototype.getField = undefined; +PieDrawer.prototype.draw = function() { + var svg = d3.select(this.selector).append("svg") + .style("margin", "auto") + .attr("width", PieDrawer.width) + .attr("height", PieDrawer.height) + .append("g") + .attr("transform", "translate(" + PieDrawer.width / 2 + "," + PieDrawer.height / 2 + ")"); + + var text = svg.append("text") + .attr("text-anchor", "middle") + .attr("dy", ".35em") + .text(L10n.loading); + + var field_getter = this.getField; + d3.json(PieDrawer.onionoo_url + "&fields=fingerprint," + this.getFieldName(), function(error, raw_data) { + var frac_nos_oignons = 0; + raw_data['relays'].forEach(function(d) { + nos_oignons_relays.forEach(function(r) { + if (r.fingerprint == d.fingerprint) { + var value = field_getter(d); + if (value) { + frac_nos_oignons += value; + } + } + }); + }); + var frac_others = 1 - frac_nos_oignons; + + data = [ { name: L10n.nos_oignons, frac: frac_nos_oignons, color: PieDrawer.color_nos_oignons, }, + { name: L10n.others, frac: frac_others, color: PieDrawer.color_others }, ]; + + text.text(PieDrawer.formatPercent(data[0].frac)); + + var g = svg.selectAll(".arc") + .data(PieDrawer.pie(data)) + .enter().append("g") + .attr("class", "arc"); + + g.append("path") + .attr("d", PieDrawer.arc) + .style("fill", function(d) { return d.data.color; }); + + }); +} + +function ConsensusPieDrawer(selector) { + this.selector = selector; +}; +ConsensusPieDrawer.prototype = new PieDrawer(); +ConsensusPieDrawer.prototype.getSelector = function() { + return "#consensus-pie"; +}; +ConsensusPieDrawer.prototype.getFieldName = function() { + return "consensus_weight_fraction"; +}; +ConsensusPieDrawer.prototype.getField = function(r) { + return r.consensus_weight_fraction; +}; + +function ExitPieDrawer(selector) { + this.selector = selector; +}; +ExitPieDrawer.prototype = new PieDrawer(); +ExitPieDrawer.prototype.getFieldName = function() { + return "exit_probability"; +}; +ExitPieDrawer.prototype.getField = function(r) { + return r.exit_probability; +};