commit e66f00562eb39b549c6e68a8321efbc693faf125
Author: Iain R. Learmonth <[email protected]>
Date:   Fri Jan 12 00:26:26 2018 +0000

    Refactoring for the map view
    
    There were a number of "special cases" for the consensus weight vs.
    advertised bandwidth that this commit tries to reduce. As a result the
    semantics of the map analysis have changed although not with any
    noticable difference to the results.
    
    In the previous version the value for each country was determined by the
    total of the consensus weight to the total of the advertised bandwidth.
    This commit changes this to make the value for each country a mean
    average of the ratios for individual relays, and now excludes relays
    with an advertised bandwidth of 0 (or missing advertised bandwidth) and
    those relays that are not yet measured by at least 3 bandwidth
    authorities.
    
    During refactoring, tooltips have also been added to display values when
    hovering over a country.
---
 js/collections/aggregates.js | 14 +++++--
 js/models/aggregate.js       |  2 +
 js/views/aggregate/map.js    | 95 ++++++++++++++++++++++++++------------------
 templates/aggregate/map.html |  2 +-
 4 files changed, 71 insertions(+), 42 deletions(-)

diff --git a/js/collections/aggregates.js b/js/collections/aggregates.js
index 163d7fb..b7354f4 100644
--- a/js/collections/aggregates.js
+++ b/js/collections/aggregates.js
@@ -7,7 +7,7 @@ define([
 ], function($, _, Backbone, aggregateModel){
   var aggregatesCollection = Backbone.Collection.extend({
     model: aggregateModel,
-    baseurl: 
'https://onionoo.torproject.org/details?running=true&type=relay&fields=country,guard_probability,middle_probability,exit_probability,consensus_weight,consensus_weight_fraction,advertised_bandwidth,flags,as_number,as_name',
+    baseurl: 
'https://onionoo.torproject.org/details?running=true&type=relay&fields=country,guard_probability,middle_probability,exit_probability,consensus_weight,consensus_weight_fraction,advertised_bandwidth,flags,as_number,as_name,measured',
     url: '',
     aType: 'cc',
     lookup: function(options) {
@@ -70,14 +70,19 @@ define([
           if (!asAggregate) {
             if (relay.as_number !== 0) 
aggregates[aggregateKey].as.add(relay.as_number);
           }
-
           aggregates[aggregateKey].relays++;
           if ((typeof relay.guard_probability) !== "undefined") 
aggregates[aggregateKey].guard_probability += relay.guard_probability;
           if ((typeof relay.middle_probability) !== "undefined") 
aggregates[aggregateKey].middle_probability += relay.middle_probability;
           if ((typeof relay.exit_probability) !== "undefined") 
aggregates[aggregateKey].exit_probability += relay.exit_probability;
           if ((typeof relay.consensus_weight) !== "undefined") 
aggregates[aggregateKey].consensus_weight += relay.consensus_weight;
           if ((typeof relay.consensus_weight_fraction) !== "undefined") 
aggregates[aggregateKey].consensus_weight_fraction += 
relay.consensus_weight_fraction;
-          if ((typeof relay.advertised_bandwidth) !== "undefined") 
aggregates[aggregateKey].advertised_bandwidth += relay.advertised_bandwidth;
+          if ((typeof relay.advertised_bandwidth) !== "undefined" && 
relay.advertised_bandwidth > 0) {
+            aggregates[aggregateKey].advertised_bandwidth += 
relay.advertised_bandwidth;
+            if (relay.measured) {
+              aggregates[aggregateKey].consensus_weight_to_bandwidth_count++;
+              aggregates[aggregateKey].consensus_weight_to_bandwidth += 
((relay.consensus_weight*1024)/relay.advertised_bandwidth); // This is divided 
by number of relays for which data existed below to provide a mean average
+            }
+          }
           _.each(relay.flags, function(flag) {
             if (flag == "Guard") aggregates[aggregateKey].guards++;
             if (flag == "Exit") aggregates[aggregateKey].exits++;
@@ -104,6 +109,9 @@ define([
               });
             }
           }
+          if (aggregate.consensus_weight_to_bandwidth_count > 0) {
+            aggregate.consensus_weight_to_bandwidth = 
aggregate.consensus_weight_to_bandwidth/aggregate.consensus_weight_to_bandwidth_count;
+          }
           aggregatesArr.push(aggregate);
         });
         collection[options.add ? 'add' : 'reset'](aggregatesArr, options);
diff --git a/js/models/aggregate.js b/js/models/aggregate.js
index 0b85050..50740df 100644
--- a/js/models/aggregate.js
+++ b/js/models/aggregate.js
@@ -15,6 +15,8 @@ define([
           advertised_bandwidth: 0,
           consensus_weight: 0,
           consensus_weight_fraction: 0,
+          consensus_weight_to_bandwidth: 0,
+          consensus_weight_to_bandwidth_count: 0,
           relays: 0,
           guards: 0,
           exits: 0
diff --git a/js/views/aggregate/map.js b/js/views/aggregate/map.js
index 4141e7b..fce1e61 100644
--- a/js/views/aggregate/map.js
+++ b/js/views/aggregate/map.js
@@ -23,7 +23,7 @@ define([
         "middle_probability": "This map shows the total middle probability of 
each country's relays as a percentage of the middle probabilities of all relays 
in the network. This probability is calculated based on consensus weights, 
relay flags, and bandwidth weights in the consensus. Path selection depends on 
more factors, so that this probability can only be an approximation.",
         "exit_probability": "This map shows the total exit probability of each 
country's relays as a percentage of the exit probabilities of all relays in the 
network. This probability is calculated based on consensus weights, relay 
flags, and bandwidth weights in the consensus. Path selection depends on more 
factors, so that this probability can only be an approximation.",
         "advertised_bandwidth": "This map shows the total <a 
href=\"https://metrics.torproject.org/glossary.html#advertised-bandwidth\"; 
target=\"_blank\">advertised bandwidth</a> of each country's relays.",
-        "cw_bw": "This map shows the ratio of total consensus weight versus 
total advertised bandwidth for each country. Countries shown in purple have 
greater advertised bandwidth than consensus weight, indicating that they are 
underweighted. Countries shown in green have greater consensus weight than 
advertised bandwidth and so are over weighted."
+        "consensus_weight_to_bandwidth": "This map shows the average ratio of 
consensus weight to advertised bandwidth for relays in each country. Countries 
shown in purple have greater consensus weight than advertised bandwidth, 
indicating that they are overweighted. Countries shown in green have greater 
advertised bandwidth than consensus weight and so are underweighted. Relays 
that did not have an advertised bandwidth or advertise a bandwidth of zero are 
not included in this analysis. Relays that have not yet been measured by at 
least three bandwidth authorities are also not included in this map as their 
consensus weight is not based on bandwidth measurement yet."
     },
     initialize: function() {
       this.collection = new aggregatesCollection;
@@ -62,37 +62,55 @@ define([
       var maximum_value = Number.NEGATIVE_INFINITY;
       var minimum_value = Number.POSITIVE_INFINITY;
 
-      if (aggregate_property == "cw_bw") {
-        _.each(aggregates, function(aggregate) {
-          if (aggregate["advertised_bandwidth"] == 0) current_val = 0;
-            else current_val = 
(aggregate["consensus_weight"]/(aggregate["advertised_bandwidth"]/1024));
-          if (current_val > maximum_value) maximum_value = current_val;
-          if (current_val < minimum_value) minimum_value = current_val;
-       });
-       var getCountryAggregate = function(code, aggregate_property) {
-         var found = 0;
-         _.each(aggregates, function(aggregate) {
-           if (aggregate.country.toUpperCase() == code)
-           if (aggregate["advertised_bandwidth"] == 0) found = 0;
-           else 
found=aggregate["consensus_weight"]/(aggregate["advertised_bandwidth"]/1024);
-         });
-         if (found < 1 && found > 0) {
-           return 1/(Math.sqrt(found/minimum_value));
-         } else {
-           return 0-Math.sqrt(found/maximum_value);
-         }
-       }
-     } else {
+      _.each(aggregates, function(aggregate) {
+        current_val = aggregate[aggregate_property];
+        if (current_val > maximum_value) maximum_value = current_val;
+        if (current_val !== 0 && current_val < minimum_value) minimum_value = 
current_val;
+      });
+
+      var getCountryAggregate = function(code, aggregate_property) {
+        var found = 0;
         _.each(aggregates, function(aggregate) {
-          if (aggregate[aggregate_property] > maximum_value) maximum_value = 
aggregate[aggregate_property];
+          if (aggregate.country.toUpperCase() == code) found = 
aggregate[aggregate_property];
         });
-        var getCountryAggregate = function(code, aggregate_property) {
-          var found = 0;
-          _.each(aggregates, function(aggregate) {
-            if (aggregate.country.toUpperCase() == code) found = 
aggregate[aggregate_property];
-          });
-        return (found == 0) ? found : Math.sqrt(found/maximum_value);
+        return found;
+      }
+
+      var getCountryFillOpacity = function(code, aggregate_property) {
+        found = getCountryAggregate(code, aggregate_property);
+        if (aggregate_property == "consensus_weight_to_bandwidth") {
+          if (found == 0) {
+            return 0;
+          } else {
+            return (found < 1) ? -(1/found)/(1/minimum_value) : 
found/maximum_value;
+          }
+        } else {
+          return found/maximum_value;
+        }
+      }
+
+      var getCountryTooltip = function(code, aggregate_property) {
+        found = getCountryAggregate(code, aggregate_property);
+        text = CountryCodes[code.toLowerCase()] + " (" + code + ") - ";
+        switch (aggregate_property) {
+          case "consensus_weight_fraction":
+          case "guard_probability":
+          case "middle_probability":
+          case "exit_probability":
+              text += (found*100).toFixed(3) + "%";
+              break;
+          case "advertised_bandwidth":
+              text += found + "KBps";
+              break;
+          case "consensus_weight_to_bandwidth":
+              if (found == 0) {
+                text += "No relays";
+              } else {
+                text += (found<1) ? "1:" + (1/found).toFixed(1) :
+                                    found.toFixed(1) + ":1";
+              }
         }
+        return text;
       }
 
       d3.json("json/countries.topo.json", function(error, us) {
@@ -119,11 +137,11 @@ define([
         .enter()
           .append("path")
             .attr("id", function(d) { return d.id; })
-            .style("fill", function(d) { return (getCountryAggregate(d.id, 
aggregate_property) > 0) ? "#7d4698" : "#68b030"; })
-            .style("fill-opacity", function(d) { return 
Math.abs(getCountryAggregate(d.id, aggregate_property)); })
+            .style("fill", function(d) { return (getCountryFillOpacity(d.id, 
aggregate_property) > 0) ? "#7d4698" : "#68b030"; })
+            .style("fill-opacity", function(d) { return 
Math.abs(getCountryFillOpacity(d.id, aggregate_property)); })
             .attr("d", path)
           .append("svg:title")
-            .text( function(d) { return d.id; });
+            .text( function(d) { return getCountryTooltip(d.id, 
aggregate_property); });
 
 
     function append_legend() {
@@ -151,18 +169,19 @@ define([
           .style("fill", "#484848")
           .text( function() {
             return (aggregate_property == "advertised_bandwidth") ?
-             "" + (Math.pow(i,2)* maximum_value/(1024*1024)).toFixed(2) + 
"MiB/s" :
-             "" + (Math.pow(i,2)* maximum_value*100).toFixed(3) + "%";
+             "" + (i * maximum_value/(1024*1024)).toFixed(2) + "MiB/s" :
+             "" + (i * maximum_value*100).toFixed(3) + "%";
           });
        }
     }
-  if (aggregate_property == "cw_bw") {
+
+  if (aggregate_property == "consensus_weight_to_bandwidth") {
       legend = (maximum_value > 1) ? 0 : 1;
       current_box = 0;
       for (var i = legend; i <= 2 ; i += 0.2) {
         j = Math.abs(i-1);
-        current_value = (i<1) ? (Math.pow(j,2)*maximum_value) :
-                                (Math.pow(j,2)*(1/minimum_value));
+        current_value = (i<1) ? (j*maximum_value) :
+                                (j*(1/minimum_value));
         if (current_value < 1)
           continue;
         svg.append("rect")
@@ -177,7 +196,7 @@ define([
           .attr("y", height-(current_box*5+1)*20)
           .attr("height", "10")
           .attr("width", "15")
-          .style("fill", function() { return (i>1) ? "#7d4698" : "#68b030"; })
+          .style("fill", function() { return (i<1) ? "#7d4698" : "#68b030"; })
           .style("fill-opacity", function() { return j; })
           .style("stroke", "#484848");
 
diff --git a/templates/aggregate/map.html b/templates/aggregate/map.html
index 2f0a0bb..96716b6 100644
--- a/templates/aggregate/map.html
+++ b/templates/aggregate/map.html
@@ -56,7 +56,7 @@
      <label class="radio-inline"><input type="radio" name="aggregate-property" 
value="middle_probability"> Middle Probability</label>
      <label class="radio-inline"><input type="radio" name="aggregate-property" 
value="exit_probability"> Exit Probability</label>
      <label class="radio-inline"><input type="radio" name="aggregate-property" 
value="advertised_bandwidth"> Advertised Bandwidth</label>
-     <label class="radio-inline"><input type="radio" name="aggregate-property" 
value="cw_bw"> Consensus Weight versus Bandwidth</label>
+     <label class="radio-inline"><input type="radio" name="aggregate-property" 
value="consensus_weight_to_bandwidth"> Consensus Weight to Bandwidth 
Ratio</label>
    </form>
    <a class="btn btn-primary" href="#aggregate/cc<%= (query) ? "/" + query : 
"" %>">View Table</a>
    <a class="btn btn-secondary" id="save_svg">Save Map</a>



_______________________________________________
tor-commits mailing list
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to