]> nos-oignons.net Git - website.git/blob - Services/Participation.html
e3edb6522be22ee7f6f66499fea1a8d91f1cfdc2
[website.git] / Services / Participation.html
1 [[!meta script="assets/relays"]]
2 [[!meta script="assets/d3/d3.v3.min"]]
3
4 <style type="text/css">
5
6 .arc path {
7   stroke: #fff;
8 }
9
10 </style>
11
12 <div style="float: left; width: 45%">
13   <h2 style="text-align: center;">Consensus weight</h2>
14   <div id="consensus-pie"></div>
15 </div>
16 <div style="float: left; width: 45%; margin-left: 3%">
17   <h2 style="text-align: center;">Exit probability</h2>
18   <div id="exit-pie"></div>
19 </div>
20 <div style="clear: left;"></div>
21
22 <script type="text/javascript">
23
24 var width = 250,
25     height = 250,
26     radius = Math.min(width, height) / 2,
27     formatPercent = d3.format(".2%");
28
29 var color_nos_oignons = "#ffa430";
30 var color_others = "#57075f";
31
32 var arc = d3.svg.arc()
33     .outerRadius(radius - 30)
34     .innerRadius(radius - 80);
35
36 var labelRadius = radius - 15;
37
38 var pie = d3.layout.pie()
39     .sort(null)
40     .value(function(d) { return d.frac; });
41
42 var onionoo_url = "https://onionoo.torproject.org/details?type=relay&contact=adminsys@nos-oignons.net";
43
44 var search_terms = "";
45 nos_oignons_relays.forEach(function(r) {
46   search_terms += " $" + r.fingerprint
47 });
48
49 function PieDrawer() { };
50 PieDrawer.prototype.getSelector = undefined;
51 PieDrawer.prototype.getFieldName = undefined;
52 PieDrawer.prototype.getField = undefined;
53 PieDrawer.prototype.draw = function() {
54   var svg = d3.select(this.getSelector()).append("svg")
55       .style("margin", "auto")
56       .attr("width", width)
57       .attr("height", height)
58     .append("g")
59       .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
60
61   var text = svg.append("text")
62       .attr("text-anchor", "middle")
63       .attr("dy", ".35em")
64       .text("Loading…");
65
66   var field_getter = this.getField;
67   d3.json(onionoo_url + "&fields=fingerprint," + this.getFieldName(), function(error, raw_data) {
68     var frac_nos_oignons = 0;
69     raw_data['relays'].forEach(function(d) {
70       nos_oignons_relays.forEach(function(r) {
71         if (r.fingerprint == d.fingerprint) {
72           var value = field_getter(d);
73           if (value) {
74             frac_nos_oignons += value;
75           }
76         }
77       });
78     });
79     var frac_others = 1 - frac_nos_oignons;
80
81     data = [ { name: 'Nos oignons', frac: frac_nos_oignons, color: color_nos_oignons, },
82              { name: 'Others',      frac: frac_others,      color: color_others }, ];
83
84     text.text(formatPercent(data[0].frac));
85
86     var g = svg.selectAll(".arc")
87         .data(pie(data))
88       .enter().append("g")
89         .attr("class", "arc");
90
91     g.append("path")
92         .attr("d", arc)
93         .style("fill", function(d) { return d.data.color; });
94
95   });
96 }
97
98 function ConsensusPieDrawer() { };
99 ConsensusPieDrawer.prototype = new PieDrawer();
100 ConsensusPieDrawer.prototype.getSelector = function() {
101   return "#consensus-pie";
102 };
103 ConsensusPieDrawer.prototype.getFieldName = function() {
104   return "consensus_weight_fraction";
105 };
106 ConsensusPieDrawer.prototype.getField = function(r) {
107   return r.consensus_weight_fraction;
108 };
109
110 function ExitPieDrawer() { };
111 ExitPieDrawer.prototype = new PieDrawer();
112 ExitPieDrawer.prototype.getSelector = function() {
113   return "#exit-pie";
114 };
115 ExitPieDrawer.prototype.getFieldName = function() {
116   return "exit_probability";
117 };
118 ExitPieDrawer.prototype.getField = function(r) {
119   return r.exit_probability;
120 };
121 /*
122 new ConsensusPieDrawer().draw();
123 new ExitPieDrawer().draw();
124 */
125 </script>
126
127 <h2>Bandwidth</h2>
128
129 <h3>3 days / read</h3>
130 <div id="bandwidth-3d-read"></div>
131 <h3>3 days / write</h3>
132 <div id="bandwidth-3d-write"></div>
133 <h3>1 week / read</h3>
134 <div id="bandwidth-1w-read"></div>
135 <h3>1 week / write</h3>
136 <div id="bandwidth-1w-write"></div>
137 <h3>1 month / read</h3>
138 <div id="bandwidth-1m-read"></div>
139 <h3>1 month / write</h3>
140 <div id="bandwidth-1m-write"></div>
141 <h3>3 months / read</h3>
142 <div id="bandwidth-3m-read"></div>
143 <h3>3 months / write</h3>
144 <div id="bandwidth-3m-write"></div>
145 <h3>1 year / read</h3>
146 <div id="bandwidth-1y-read"></div>
147 <h3>1 year / write</h3>
148 <div id="bandwidth-1y-write"></div>
149
150 <style type="text/css">
151
152 .axis path,
153 .axis line {
154   fill: none;
155   stroke: #000;
156   shape-rendering: crispEdges;
157 }
158
159 </style>
160
161 <script type="text/javascript">
162
163 var margin = {top: 50, right: 90, bottom: 90, left: 130},
164     width = 700 - margin.left - margin.right,
165     height = 400 - margin.top - margin.bottom;
166
167 var parseTime = d3.time.format("%Y-%m-%d %H:%M:%S").parse,
168     bwFormatter = d3.format(".f");
169
170 var x = d3.time.scale()
171     .range([0, width]);
172
173 var y = d3.scale.linear()
174     .range([height, 0]);
175
176 var color = d3.scale.category20();
177
178 var xAxis = d3.svg.axis()
179     .scale(x)
180     .orient("bottom");
181
182 var yAxis = d3.svg.axis()
183     .scale(y)
184     .orient("left")
185     .tickFormat(function(d) { return (d == 0) ? "" : bwFormatter(Math.abs(d)) + " Mbit/s " + ((d > 0) ? "in" : "out"); });
186
187 var area = d3.svg.area()
188     .x(function(d) { return x(d.date); })
189     .y0(function(d) { return y(d.y0); })
190     .y1(function(d) { return y(d.y0 + d.y); });
191
192 var read_stack = d3.layout.stack()
193     .values(function(d) { console.log(JSON.stringify(d)); return d.read_values; });
194 var write_stack = d3.layout.stack()
195     .values(function(d) { console.log(JSON.stringify(d)); return d.write_values; })
196     .y(function(d) { return -d.y; });
197
198 var onionoo_url = "https://onionoo.torproject.org/bandwidth?type=relay&contact=adminsys@nos-oignons.net";
199
200 function extract_values(history, minTime, maxTime) {
201   var values = [];
202   var first = parseTime(history.first);
203   var last = parseTime(history.last);
204   var i = 0;
205   for (var current = minTime; current <= maxTime; current = d3.time.second.offset(current, history.interval)) {
206     if (first <= current && current <= last) {
207       values.push({ date: current, y: history.factor * history.values[i++] * 8 / 1000000 });
208     }
209   }
210   return values;
211 }
212
213 function draw_bandwidth_graph(raw_data, selector, period) {
214   var svg = d3.select(selector).append("svg")
215       .attr("width", width + margin.left + margin.right)
216       .attr("height", height + margin.top + margin.bottom)
217     .append("g")
218       .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
219
220   var valid_fingerprints = [];
221   nos_oignons_relays.forEach(function(r) {
222     var relay_data = raw_data["relays"].filter(function(d) { return d.fingerprint == r.fingerprint; })[0];
223     if (relay_data && relay_data['read_history'][period] && relay_data['write_history'][period]) {
224       valid_fingerprints.push(r.fingerprint);
225     }
226   });
227   color.domain(valid_fingerprints);
228
229   var minTime = d3.max(raw_data.relays.map(function(d) {
230         return d['read_history'][period] && parseTime(d['read_history'][period].first) &&
231                d['write_history'][period] && parseTime(d['write_history'][period].first);
232       }));
233   var maxTime = d3.min(raw_data.relays.map(function(d) {
234         return d['read_history'][period] && parseTime(d['read_history'][period].last) &&
235                d['write_history'][period] && parseTime(d['write_history'][period].last);
236       }));
237   var maxReadBandwidth = 0;
238   var maxWriteBandwidth = 0;
239
240   var data = color.domain().map(function(fingerprint) {
241         var relay_data = raw_data["relays"].filter(function(d) { return d.fingerprint == fingerprint; })[0];
242         var read_history = relay_data['read_history'][period];
243         var write_history = relay_data['write_history'][period];
244         var read_values = extract_values(read_history, minTime, maxTime);
245         var write_values = extract_values(write_history, minTime, maxTime);
246
247         maxReadBandwidth = maxReadBandwidth + d3.max(read_values.map(function(d) { return d.y; }));
248         maxWriteBandwidth = maxWriteBandwidth + d3.max(write_values.map(function(d) { return d.y; }));
249
250         return {
251           fingerprint: fingerprint,
252           read_values: read_values,
253           write_values: write_values,
254         };
255       });
256
257   x.domain([minTime, maxTime]);
258   y.domain([-maxWriteBandwidth, maxReadBandwidth]);
259
260   var read_graph = svg.selectAll(".read_graph")
261       .data(read_stack(data))
262     .enter().append("g")
263       .attr("class", "read_graph");
264   read_graph.append("path")
265       .attr("class", "area")
266       .attr("d", function(d) { return area(d.read_values); })
267       .style("fill", function(d) { return color(d.fingerprint); });
268
269   var write_graph = svg.selectAll(".write_graph")
270       .data(write_stack(data))
271     .enter().append("g")
272       .attr("class", "write_graph");
273   write_graph.append("path")
274       .attr("class", "area")
275       .attr("d", function(d) { return area(d.write_values); })
276       .style("fill", function(d) { return color(d.fingerprint); });
277
278   svg.append("g")
279       .attr("class", "x axis")
280       .attr("transform", "translate(0," + height + ")")
281       .call(xAxis)
282         .selectAll("text")
283         .style("text-anchor", "end")
284         .attr("transform", "rotate(-90) translate(-10, 0)");
285
286   svg.append("g")
287       .attr("class", "y axis")
288       .call(yAxis);
289
290   var legend = svg.selectAll(".legend")
291       .data(color.domain().slice().reverse())
292     .enter().append("g")
293       .attr("class", "legend")
294       .attr("transform", function(d, i) { return "translate(0," + ((i * 20) - margin.top) + ")"; });
295
296   legend.append("rect")
297       .attr("x", width - 18)
298       .attr("width", 18)
299       .attr("height", 18)
300       .style("fill", color);
301
302   legend.append("text")
303       .attr("x", width - 24)
304       .attr("y", 9)
305       .attr("dy", ".35em")
306       .style("text-anchor", "end")
307       .text(function(d) {
308         return nos_oignons_relays.filter(function(r) { return r.fingerprint == d; })[0].name;
309       });
310 };
311
312 d3.json(onionoo_url, function(error, raw_data) {
313   draw_bandwidth_graph(raw_data, "#bandwidth-3d-read", "3_days");
314   draw_bandwidth_graph(raw_data, "#bandwidth-3d-read", "3_months");
315 /*
316   draw_bandwidth_graph(raw_data, "#bandwidth-3d-write", "write_history", "3_days");
317   draw_bandwidth_graph(raw_data, "#bandwidth-1w-read", "read_history", "1_week");
318   draw_bandwidth_graph(raw_data, "#bandwidth-1w-write", "write_history", "1_week");
319   draw_bandwidth_graph(raw_data, "#bandwidth-1m-read", "read_history", "1_month");
320   draw_bandwidth_graph(raw_data, "#bandwidth-1m-write", "write_history", "1_month");
321   draw_bandwidth_graph(raw_data, "#bandwidth-3m-read", "read_history", "3_months");
322   draw_bandwidth_graph(raw_data, "#bandwidth-3m-write", "write_history", "3_months");
323   draw_bandwidth_graph(raw_data, "#bandwidth-1y-read", "read_history", "1_year");
324   draw_bandwidth_graph(raw_data, "#bandwidth-1y-write", "write_history", "1_year");
325 */
326 });
327
328 </script>