From b8ad28b1f40d4c9249aaef8727910ac7b4a15f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 31 Jul 2018 18:39:19 +0200 Subject: [PATCH] new: Add support for multi-country graphs --- bgpranking/querying.py | 20 ++-- website/web/__init__.py | 37 ++++--- website/web/static/linegraph.js | 8 -- website/web/static/linegraph_country.js | 113 +++++++++++++++++++++ website/web/templates/country.html | 6 +- website/web/templates/country_asn_map.html | 6 +- website/web/templates/top_forms.html | 10 +- 7 files changed, 158 insertions(+), 42 deletions(-) create mode 100644 website/web/static/linegraph_country.js diff --git a/bgpranking/querying.py b/bgpranking/querying.py index fef52e0..c31bba8 100644 --- a/bgpranking/querying.py +++ b/bgpranking/querying.py @@ -179,9 +179,9 @@ class Querying(): daily_sum = sum(ranks) return daily_sum, to_return - def country_history(self, country: str, period: int=30, source: Union[list, str]='', + def country_history(self, country: Union[list, str], period: int=30, source: Union[list, str]='', ipversion: str='v4', date: Dates=datetime.date.today()): - to_return = [] + to_return = {} if isinstance(date, str): date = parse(date).date() @@ -189,10 +189,14 @@ class Querying(): # the period to display will be around the date passed at least 2/3 before the date, at most 1/3 after date = datetime.date.today() - for i in range(period): - d = date - timedelta(days=i) - rank, details = self.country_rank(country, d, source, ipversion) - if rank is None: - rank = 0 - to_return.insert(0, (d.isoformat(), rank, list(details))) + if isinstance(country, str): + country = [country] + for c in country: + to_return[c] = [] + for i in range(period): + d = date - timedelta(days=i) + rank, details = self.country_rank(c, d, source, ipversion) + if rank is None: + rank = 0 + to_return[c].insert(0, (d.isoformat(), rank, list(details))) return to_return diff --git a/website/web/__init__.py b/website/web/__init__.py index f325079..e21018a 100644 --- a/website/web/__init__.py +++ b/website/web/__init__.py @@ -47,7 +47,10 @@ def load_session(): session['asn'] = d['asn'] session.pop('country', None) elif 'country' in d: - session['country'] = d.getlist('country') + if '_all' in d.getlist('country'): + session.pop('country', None) + else: + session['country'] = d.getlist('country') session.pop('asn', None) set_default_date_session() @@ -106,22 +109,24 @@ def country_history_callback(): mapping = defaultdict(dict) dates = [] all_asns = set([]) - for d, r_sum, details in history_data: - dates.append(d) - for detail in details: - asn, r = detail - all_asns.add(asn) - mapping[asn][d] = r + for country, data in history_data.items(): + for d, r_sum, details in data: + dates.append(d) + for detail in details: + asn, r = detail + all_asns.add(asn) + mapping[asn][d] = r - to_display = [[''] + dates] - for a in sorted(list(all_asns), key=int): - line = [a] - for d in dates: - if mapping[a].get(d) is not None: - line.append(round(mapping[a].get(d), 3)) - else: - line.append('N/A') - to_display.append(line) + to_display_temp = [[country] + dates] + for a in sorted(list(all_asns), key=int): + line = [a] + for d in dates: + if mapping[a].get(d) is not None: + line.append(round(mapping[a].get(d), 3)) + else: + line.append('N/A') + to_display_temp.append(line) + to_display.append(to_display_temp) return json.dumps(render_template('country_asn_map.html', to_display=to_display)) diff --git a/website/web/static/linegraph.js b/website/web/static/linegraph.js index e5e6389..57a0867 100644 --- a/website/web/static/linegraph.js +++ b/website/web/static/linegraph.js @@ -36,14 +36,6 @@ function linegraph(call_path) { context.lineWidth = 1.5; context.strokeStyle = "steelblue"; context.stroke(); - d3.json(call_path + '_callback', - {credentials: 'same-origin', - method: 'POST', - body: JSON.stringify(data), - // headers: {'Content-Type': 'application/json'} - }).then(function(data) { - d3.select('#asn_details').html(data); - }); }); function xAxis() { diff --git a/website/web/static/linegraph_country.js b/website/web/static/linegraph_country.js new file mode 100644 index 0000000..5a6eef9 --- /dev/null +++ b/website/web/static/linegraph_country.js @@ -0,0 +1,113 @@ +function linegraph(call_path) { + var canvas = document.querySelector("canvas"), + context = canvas.getContext("2d"); + + // set the dimensions and margins of the graph + var margin = {top: 20, right: 20, bottom: 30, left: 50}, + width = canvas.width - margin.left - margin.right, + height = canvas.height - margin.top - margin.bottom; + + // parse the date / time + var parseTime = d3.timeParse("%Y-%m-%d"); + + // set the ranges + var x = d3.scaleTime().range([0, width]); + var y = d3.scaleLinear().range([height, 0]); + var z = d3.scaleOrdinal(d3.schemeCategory10); + + // define the line + var line = d3.line() + .x(function(d) { return x(parseTime(d[0])); }) + .y(function(d) { return y(d[1]); }) + .curve(d3.curveStep) + .context(context); + + context.translate(margin.left, margin.top); + + // Get the data + d3.json(call_path, {credentials: 'same-origin'}).then(function(data) { + var color = d3.scaleOrdinal(d3.schemeCategory10); + var i = 0; + for (country in data) { + var country_data = data[country] + x.domain(d3.extent(country_data, function(d) { return parseTime(d[0]); })); + y.domain(d3.extent(country_data, function(d) { return d[1]; })); + + context.beginPath(); + line(country_data); + context.lineWidth = 1.5; + context.strokeStyle = color(i); + context.stroke(); + i += 1; + }; + xAxis(); + yAxis(); + d3.json(call_path + '_callback', + {credentials: 'same-origin', + method: 'POST', + body: JSON.stringify(data), + // headers: {'Content-Type': 'application/json'} + }).then(function(data) { + d3.select('#asn_details').html(data); + }); + }); + + function xAxis() { + var tickCount = 10, + tickSize = .1, + ticks = x.ticks(tickCount), + tickFormat = x.tickFormat(); + + context.beginPath(); + ticks.forEach(function(d) { + context.moveTo(x(d), height); + context.lineTo(x(d), height + tickSize); + }); + context.strokeStyle = "black"; + context.stroke(); + + context.textAlign = "center"; + context.textBaseline = "top"; + ticks.forEach(function(d) { + context.fillText(tickFormat(d), x(d), height + tickSize); + }); + } + + function yAxis() { + var tickCount = 20, + tickSize = 1, + tickPadding = 1, + ticks = y.ticks(tickCount), + tickFormat = y.tickFormat(tickCount); + + context.beginPath(); + ticks.forEach(function(d) { + context.moveTo(0, y(d)); + context.lineTo(-6, y(d)); + }); + context.strokeStyle = "black"; + context.stroke(); + + context.beginPath(); + context.moveTo(-tickSize, 0); + context.lineTo(0.5, 0); + context.lineTo(0.5, height); + context.lineTo(-tickSize, height); + context.strokeStyle = "black"; + context.stroke(); + + context.textAlign = "right"; + context.textBaseline = "middle"; + ticks.forEach(function(d) { + context.fillText(tickFormat(d), -tickSize - tickPadding, y(d)); + }); + + context.save(); + context.rotate(-Math.PI / 2); + context.textAlign = "right"; + context.textBaseline = "top"; + context.font = "bold 10px sans-serif"; + context.fillText("Rank", -10, 10); + context.restore(); + } +} diff --git a/website/web/templates/country.html b/website/web/templates/country.html index 7dc0b9c..c9bca22 100644 --- a/website/web/templates/country.html +++ b/website/web/templates/country.html @@ -5,17 +5,17 @@ {% endblock %} -{% block title %}Ranking - {{ country }}{% endblock %} +{% block title %}Ranking - {{ ' '.join(country) }}{% endblock %} {% block scripts %} {{ super() }} - + {% endblock %} {% block content %}
-

Ranking - {{country}}



+

Ranking - {{ ' '.join(country) }}



{% include ['top_forms.html'] %} diff --git a/website/web/templates/country_asn_map.html b/website/web/templates/country_asn_map.html index 2357c1a..ff59b6b 100644 --- a/website/web/templates/country_asn_map.html +++ b/website/web/templates/country_asn_map.html @@ -1,10 +1,11 @@ +{% for to_display_country in to_display%} - {% for date in to_display[0] %} + {% for date in to_display_country[0] %} {% endfor %} - {% for line in to_display[1:] %} + {% for line in to_display_country[1:] %} {% for rank in line[1:] %} @@ -13,6 +14,7 @@ {% endfor %}
{{ date }}
{{ line[0] }}
+{% endfor %} diff --git a/website/web/templates/top_forms.html b/website/web/templates/top_forms.html index 54efcea..40878cb 100644 --- a/website/web/templates/top_forms.html +++ b/website/web/templates/top_forms.html @@ -11,10 +11,10 @@
- + {% for s in sources %} - + {% endfor %} @@ -25,9 +25,9 @@