tor-commits
Threads by month
- ----- 2025 -----
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
February 2021
- 19 participants
- 1772 discussions
commit 0981e1069260c6cd1ebadf1139c33ace4c2d1031
Author: juga0 <juga(a)riseup.net>
Date: Wed Feb 17 16:58:33 2021 +0000
fix: doc: Add target to call plantuml
and generate .svg from .puml files.
Do not add to the html target since the generated svg images are
not deterministic and will change every time `plantuml` is call.
---
docs/Makefile | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/docs/Makefile b/docs/Makefile
index eee14f8..40a6b5d 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -13,6 +13,8 @@ BUILDDIRIMAGES = $(BUILDDIR)/html/_images
PYREVERSE = pyreverse
PYREVERSE_FLAGS = -o svg -p sbws ../sbws
UMLSVG := $(PYREVERSE) $(PYREVERSE_FLAGS);mv *.svg $(IMAGEDIRS);mkdir -p $(BUILDDIRIMAGES);cp $(IMAGEDIRS)/*.svg $(BUILDDIRIMAGES)
+PLANTUML := plantuml
+PLANTUML_CMD := $(PLANTUML) -tsvg -o ../$(IMAGEDIRS) $(SOURCEDIR)/*.puml
# Put it first so that "make" without argument is like "make help".
help:
@@ -24,6 +26,10 @@ umlsvg:
@echo "Generating UML SVG"
$(UMLSVG)
+plantuml:
+ @echo "Generating plantuml .svg files."
+ $(PLANTUML_CMD)
+
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
1
0
commit 7c1db0ac9dc188eada5cf37a53447e3a4b370a0e
Author: juga0 <juga(a)riseup.net>
Date: Wed Feb 17 16:34:14 2021 +0000
fix: doc: Add missing new lines
---
docs/source/how_works.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/source/how_works.rst b/docs/source/how_works.rst
index f4b1ae0..ff9b999 100644
--- a/docs/source/how_works.rst
+++ b/docs/source/how_works.rst
@@ -130,6 +130,7 @@ Running the generator
-----------------------
Every hour, the generator:
+
#. Aggregate all the measurements (not older than 6 six days) for every relay.
#. Filter the measurements
#. Scale the measurements
1
0

[sbws/maint-1.1] fix: doc: Separate how scanner and generator work
by juga@torproject.org 26 Feb '21
by juga@torproject.org 26 Feb '21
26 Feb '21
commit ece2e2d60a7d52175940a5275c45e9fdd09ccdae
Author: juga0 <juga(a)riseup.net>
Date: Wed Feb 17 16:47:25 2021 +0000
fix: doc: Separate how scanner and generator work
in different files and link to each other.
---
docs/source/generator.rst | 50 ++++++++++++++++++++++++++++++++++++
docs/source/how_works.rst | 65 ++++++++---------------------------------------
docs/source/index.rst | 1 +
3 files changed, 61 insertions(+), 55 deletions(-)
diff --git a/docs/source/generator.rst b/docs/source/generator.rst
new file mode 100644
index 0000000..ef94703
--- /dev/null
+++ b/docs/source/generator.rst
@@ -0,0 +1,50 @@
+.. _generator:
+
+How the Bandwidth File is generated
+===================================
+
+.. seealso:: :ref:`scanner`.
+
+Every hour, the generator:
+
+#. Aggregate all the measurements (not older than 6 six days) for every relay.
+#. Filter the measurements
+#. Scale the measurements
+#. Write the bandwidth file
+
+Source code: :func:`sbws.lib.v3bwfile.V3BWFile.from_results`
+
+Filtering the bandwidth measurements
+-------------------------------------
+
+Each relay bandwidth measurements are selected in the following way:
+
+#. At least two bandwidth measurements (``Result`` s) MUST have been obtained
+ within an arbitrary number of seconds (currently one day).
+ If they are not, the relay MUST NOT be included in the Bandwith File.
+#. The measurements than are are older than an arbitrary number of senconds
+ in the past MUST be discarded.
+ Currently this number is the same as ``data_period`` (5 days) when not
+ scaling as Torflow and 28 days when scaling as Torflow.
+
+If the number of relays to include in the Bandwidth File are less than
+a percententage (currently 60%) than the number of relays in the consensus,
+additional Header Lines MUST be added (see XXX) to the Bandwith File and the
+relays SHOULD NOT be included.
+
+Scaling the bandwidth measurements
+------------------------------------
+
+Consensus bandwidth obtained by new implementations MUST be comparable to the
+consensus bandwidth, therefore they MUST implement torflow_scaling_.
+The bandwidth_file_spec_ appendix B describes torflow scaling and a linear
+scaling method.
+
+Writing the bandwidth file
+---------------------------
+
+The bandwidth file format is defined in the bandwidth_file_spec_.
+
+
+.. _torflow_scaling: https://gitweb.torproject.org/torflow.git/tree/NetworkScanners/BwAuthority/…
+.. _bandwidth_file_spec: https://gitweb.torproject.org/torspec.git/tree/bandwidth-file-spec.txt
diff --git a/docs/source/how_works.rst b/docs/source/how_works.rst
index ff9b999..ebe4cf9 100644
--- a/docs/source/how_works.rst
+++ b/docs/source/how_works.rst
@@ -1,11 +1,10 @@
-What the scanner and the generator do
-======================================
+.. _scanner:
-Running the scanner
------------------------
+How sbws works
+==============
Overview
-~~~~~~~~~
+---------
.. The following text is part of the introduction in the README, but rst
formatted.
@@ -28,7 +27,7 @@ by a :term:`directory authority` to report relays’ bandwidth in its vote.
.. image:: ./images/dirauths_bwauths.png
Intialization
-~~~~~~~~~~~~~~
+--------------
.. At some point it should be able to get environment variables
@@ -58,7 +57,7 @@ Classes used in the initialization:
Source code: :func:`sbws.core.scanner.run_speedtest`
Measuring relays
-~~~~~~~~~~~~~~~~~
+-----------------
#. For every relay:
#. Select a second relay to build a Tor circuit.
@@ -84,7 +83,7 @@ Measuring a relay
Source code: :func:`sbws.core.scanner.measure_relay`
Selecting a second relay
-~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------
#. If the relay to measure is an exit, use it as an exit and obtain the
non-exits.
@@ -102,7 +101,7 @@ Selecting a second relay
Source code: :func:`sbws.core.scanner.measure_relay`
Selecting the data to download
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------------------
#. While the downloaded data is smaller than 1GB or the number of download
is minor than 5:
@@ -116,7 +115,7 @@ Selecting the data to download
Source code: :func:`sbws.core.scanner._should_keep_result`
Writing the measurements to the filesystem
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------------------------------
For every measured relay, the measurement result is put in a queue.
There's an independent thread getting measurements from the queue every second.
@@ -126,54 +125,10 @@ The file is named with the current date. Every day a new file is created.
Source code: :func:`sbws.lib.resultdump.ResultDump.enter`
-Running the generator
------------------------
-
-Every hour, the generator:
-
-#. Aggregate all the measurements (not older than 6 six days) for every relay.
-#. Filter the measurements
-#. Scale the measurements
-#. Write the bandwidth file
-
-Source code: :func:`sbws.lib.v3bwfile.V3BWFile.from_results`
-
-Filtering the bandwidth measurements
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Each relay bandwidth measurements are selected in the following way:
-
-#. At least two bandwidth measurements (``Result`` s) MUST have been obtained
- within an arbitrary number of seconds (currently one day).
- If they are not, the relay MUST NOT be included in the Bandwith File.
-#. The measurements than are are older than an arbitrary number of senconds
- in the past MUST be discarded.
- Currently this number is the same as ``data_period`` (5 days) when not
- scaling as Torflow and 28 days when scaling as Torflow.
-
-If the number of relays to include in the Bandwidth File are less than
-a percententage (currently 60%) than the number of relays in the consensus,
-additional Header Lines MUST be added (see XXX) to the Bandwith File and the
-relays SHOULD NOT be included.
-
-Scaling the bandwidth measurements
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Consensus bandwidth obtained by new implementations MUST be comparable to the
-consensus bandwidth, therefore they MUST implement torflow_scaling_.
-The bandwidth_file_spec_ appendix B describes torflow scaling and a linear
-scaling method.
-
-Writing the bandwidth file
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The bandwidth file format is defined in the bandwidth_file_spec_.
-
+.. seealso:: :ref:`generator`.
.. _torflow: https://gitweb.torproject.org/torflow.git
.. _stem: https://stem.torproject.org
.. https://github.com/requests/requests/issues/4885
.. _requests: http://docs.python-requests.org/
.. _peerflow: https://www.nrl.navy.mil/itd/chacs/sites/www.nrl.navy.mil.itd.chacs/files/p…
-.. _torflow_scaling: https://gitweb.torproject.org/torflow.git/tree/NetworkScanners/BwAuthority/…
-.. _bandwidth_file_spec: https://gitweb.torproject.org/torspec.git/tree/bandwidth-file-spec.txt
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 58c3911..53c3886 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -40,6 +40,7 @@ Included in the
testing
documenting
how_works
+ generator
code_design
state
config
1
0

26 Feb '21
commit 81fef71ddfb7b34e6a7797b34593cf709e4c6caf
Author: juga0 <juga(a)riseup.net>
Date: Thu Feb 18 12:27:29 2021 +0000
fix: docs: Rename section, add diagrams
---
docs/source/activity_aggr_file.puml | 27 ++++++++++++
docs/source/activity_aggr_lines.puml | 36 ++++++++++++++++
docs/source/activity_scaling_as_torflow.puml | 35 ++++++++++++++++
docs/source/generator.rst | 20 +++++++--
docs/source/images/activity_aggr_file.svg | 40 ++++++++++++++++++
docs/source/images/activity_aggr_lines.svg | 49 ++++++++++++++++++++++
docs/source/images/activity_scaling_as_torflow.svg | 47 +++++++++++++++++++++
7 files changed, 251 insertions(+), 3 deletions(-)
diff --git a/docs/source/activity_aggr_file.puml b/docs/source/activity_aggr_file.puml
new file mode 100644
index 0000000..04be253
--- /dev/null
+++ b/docs/source/activity_aggr_file.puml
@@ -0,0 +1,27 @@
+@startuml
+
+title Activity diagram sbws relays exclusion (V3BWFile.from_results)
+
+start
+:router_statuses_d;
+while (results.items()?)
+ :line, reason = V3BWLine.from_results();
+ if (not reason?) then (yes)
+ :bwlines_raw.append(line);
+ else (no)
+ :bw_lines_excluded.append(line);
+ :exclusion_dict[reason] = exclusion_dict.get(reason, 0) + 1;
+ endif
+endwhile
+:header.add_relays_excluded_counters(exclusion_dict);
+if (not bw_lines_raw?) then (yes)
+ :return (header, bw_lines_excluded);
+ stop
+endif
+if (scaling_method == TORFLOW?) then (yes)
+ :bw_lines = cls.bw_torflow_scale();
+endif
+:return (header, bw_lines + bw_lines_excluded);
+stop
+
+@enduml
diff --git a/docs/source/activity_aggr_lines.puml b/docs/source/activity_aggr_lines.puml
new file mode 100644
index 0000000..b9b9e42
--- /dev/null
+++ b/docs/source/activity_aggr_lines.puml
@@ -0,0 +1,36 @@
+@startuml
+
+title Activity diagram sbws results exclussion and aggregation (V3BWLine.from_results)
+
+start
+:success_results;
+if (not success_results?) then (yes)
+ :return (, exclusion_reason);
+ stop
+endif
+:results_away;
+if (not results_away?) then (yes)
+ :return (, exclusion_reason);
+ stop
+endif
+:results_recent;
+if (not results_recent?) then (yes)
+ :return (, exclusion_reason);
+ stop
+endif
+if (node_id in router_statuses_d?) then (yes)
+ :consensus_bandwidth;
+else (no)
+ :consensus_bandwidth;
+endif
+:obs_last;
+if (obs_last is None and consensus_bandwidth is None?) then (yes)
+ :return(cls(node_id, 1), "no_consensus_no_observed_bw");
+ stop
+endif
+:bw;
+:kwargs[...];
+:return (node_id, bw, **kwargs), None;
+stop
+
+@enduml
diff --git a/docs/source/activity_scaling_as_torflow.puml b/docs/source/activity_scaling_as_torflow.puml
new file mode 100644
index 0000000..65a4457
--- /dev/null
+++ b/docs/source/activity_scaling_as_torflow.puml
@@ -0,0 +1,35 @@
+@startuml
+
+title Activity diagram sbws bw_torflow_scale
+
+start
+'bw_lines: the relays' raw measurements
+:mu = mean([l.bw_mean for l in bw_lines]);
+:muf = mean([l.bw_filt for l in bw_lines]);
+:sum_bw = 0;
+while (for l in bw_lines?)
+ :bw_obs;
+ :desc_bw = min(desc_bw_obs, l.desc_bw_bur, l.desc_bw_avg);
+ :min_bandwidth = min(desc_bw, l.consensus_bandwidth);
+ :ratio_stream = l.bw_mean / mu;
+ :ratio_stream_filtered = l.bw_filt / muf;
+ :ratio = max(ratio_stream, ratio_stream_filtered);
+ :l.bw = ratio * min_bandwidth;
+ if (router_statuses_d?) then (yes)
+ if (l.node_id in router_statuses_d?) then (yes)
+ :sum_bw += l.bw;
+ endif
+ else (no)
+ :sum_bw += l.bw;
+ endif
+endwhile
+:hlimit = sum_bw * cap;
+while (for l in bw_lines?)
+ :bw_scaled = min(hlimit, l.bw);
+ :l.bw = kb_round_x_sig_dig(bw_scaled, digits=num_round_dig);
+endwhile
+:return sorted(bw_lines_tf, key=lambda x: x.bw, reverse=reverse);
+stop
+
+footer last updated 2021-01-08
+@enduml
diff --git a/docs/source/generator.rst b/docs/source/generator.rst
index ef94703..7d43d33 100644
--- a/docs/source/generator.rst
+++ b/docs/source/generator.rst
@@ -1,9 +1,9 @@
.. _generator:
-How the Bandwidth File is generated
-===================================
+How aggregation and scaling works
+=================================
-.. seealso:: :ref:`scanner`.
+.. seealso:: :ref:`scanner` (scanner part).
Every hour, the generator:
@@ -14,6 +14,8 @@ Every hour, the generator:
Source code: :func:`sbws.lib.v3bwfile.V3BWFile.from_results`
+.. _filtering-measurements:
+
Filtering the bandwidth measurements
-------------------------------------
@@ -32,14 +34,26 @@ a percententage (currently 60%) than the number of relays in the consensus,
additional Header Lines MUST be added (see XXX) to the Bandwith File and the
relays SHOULD NOT be included.
+.. image:: ./images/activity_aggr_file.svg
+
+.. image:: ./images/activity_aggr_lines.svg
+
+.. _scaling-the-bandwidth-measurements:
+
Scaling the bandwidth measurements
------------------------------------
Consensus bandwidth obtained by new implementations MUST be comparable to the
consensus bandwidth, therefore they MUST implement torflow_scaling_.
+
The bandwidth_file_spec_ appendix B describes torflow scaling and a linear
scaling method.
+.. image:: ./images/activity_scaling_as_torflow.svg
+
+.. seealso:: :ref:`torflow_aggr` and :ref:`differences`.
+
+
Writing the bandwidth file
---------------------------
diff --git a/docs/source/images/activity_aggr_file.svg b/docs/source/images/activity_aggr_file.svg
new file mode 100644
index 0000000..34d0aed
--- /dev/null
+++ b/docs/source/images/activity_aggr_file.svg
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="874px" preserveAspectRatio="none" style="width:663px;height:874px;" version="1.1" viewBox="0 0 663 874" width="663px" zoomAndPan="magnify"><defs><filter height="300%" id="f1enb2bzhjec9f" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><text fill="#000000" font-family="sans-serif" font-size="18" lengthAdjust="spacingAndGlyphs" textLength="547" x="57" y="26.708">Activity diagram sbws relays exclusion V3BWFile.from_results</text><ellipse cx="278.25" cy="40.9531" fill="#000000" filter="url(#f1enb2bz
hjec9f)" rx="10" ry="10" style="stroke: none; stroke-width: 1.0;"/><rect fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="134" x="211.25" y="70.9531"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="114" x="221.25" y="92.0918">router_statuses_d</text><rect fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="263" x="146.75" y="168.9219"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="243" x="156.75" y="190.0605">line, reason = V3BWLine.from_results()</text><polygon fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" points="244.25,222.8906,312.25,222.8906,324.25,234.8906,312.25,246.8906,244.25,246.8906,232.25,234.8906,244.25,222.8906" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="san
s-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="68" x="244.25" y="238.6987">not reason?</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="212.25" y="232.2964">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="324.25" y="232.2964">no</text><rect fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="178" x="38" y="256.8906"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="158" x="48" y="278.0293">bwlines_raw.append(line)</text><rect fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="218" x="320.5" y="256.8906"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength=
"198" x="330.5" y="278.0293">bw_lines_excluded.append(line)</text><rect fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="387" x="236" y="310.8594"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="367" x="246" y="331.998">exclusion_dict[reason] = exclusion_dict.get(reason, 0) + 1</text><polygon fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" points="278.25,350.8281,290.25,362.8281,278.25,374.8281,266.25,362.8281,278.25,350.8281" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" points="233.25,124.9219,323.25,124.9219,335.25,136.9219,323.25,148.9219,233.25,148.9219,221.25,136.9219,233.25,124.9219" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="90" x="233.25" y="140.73">results.items()?</text><rect fi
ll="#FEFECE" filter="url(#f1enb2bzhjec9f)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="357" x="99.75" y="416.8281"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="337" x="109.75" y="437.9668">header.add_relays_excluded_counters(exclusion_dict)</text><rect fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="240" x="158.25" y="519.1992"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="220" x="168.25" y="540.3379">return (header, bw_lines_excluded)</text><ellipse cx="278.25" cy="590.6836" fill="none" filter="url(#f1enb2bzhjec9f)" rx="10" ry="10" style="stroke: #000000; stroke-width: 1.0;"/><ellipse cx="278.75" cy="591.1836" fill="#000000" filter="url(#f1enb2bzhjec9f)" rx="6" ry="6" style="stroke: none; stroke-width: 1.0;"/><polygon fill="#FEFECE" fil
ter="url(#f1enb2bzhjec9f)" points="226.25,470.7969,330.25,470.7969,342.25,482.7969,330.25,494.7969,226.25,494.7969,214.25,482.7969,226.25,470.7969" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="282.25" y="505.0073">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="104" x="226.25" y="486.605">not bw_lines_raw?</text><rect fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="225" x="165.75" y="691.0859"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="205" x="175.75" y="712.2246">bw_lines = cls.bw_torflow_scale()</text><polygon fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" points="191.25,642.6836,365.25,642.6836,377.25,654.6836,365.25,666.6836,191.25,666.6836,179.25,654.6836,191
.25,642.6836" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="282.25" y="676.894">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="174" x="191.25" y="658.4917">scaling_method == TORFLOW?</text><polygon fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" points="278.25,745.0547,290.25,757.0547,278.25,769.0547,266.25,757.0547,278.25,745.0547" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="url(#f1enb2bzhjec9f)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="310" x="123.25" y="789.0547"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="290" x="133.25" y="810.1934">return (header, bw_lines + bw_lines_excluded)</text><ellipse cx="278.25" cy="853.0234" fill="none" filter="url(#f1enb2bzhjec9f)" rx="10" r
y="10" style="stroke: #000000; stroke-width: 1.0;"/><ellipse cx="278.75" cy="853.5234" fill="#000000" filter="url(#f1enb2bzhjec9f)" rx="6" ry="6" style="stroke: none; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="50.9531" y2="70.9531"/><polygon fill="#A80036" points="274.25,60.9531,278.25,70.9531,282.25,60.9531,278.25,64.9531" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="429.5" x2="429.5" y1="290.8594" y2="310.8594"/><polygon fill="#A80036" points="425.5,300.8594,429.5,310.8594,433.5,300.8594,429.5,304.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="232.25" x2="127" y1="234.8906" y2="234.8906"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="127" x2="127" y1="234.8906" y2="256.8906"/><polygon fill="#A80036" points="123,246.8906,127,256.8906,131,246.8906,127,250.8906" style="stroke: #A80036; stroke-width: 1.0;"/><lin
e style="stroke: #A80036; stroke-width: 1.5;" x1="324.25" x2="429.5" y1="234.8906" y2="234.8906"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="429.5" x2="429.5" y1="234.8906" y2="256.8906"/><polygon fill="#A80036" points="425.5,246.8906,429.5,256.8906,433.5,246.8906,429.5,250.8906" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="127" x2="127" y1="290.8594" y2="362.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="127" x2="266.25" y1="362.8281" y2="362.8281"/><polygon fill="#A80036" points="256.25,358.8281,266.25,362.8281,256.25,366.8281,260.25,362.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="429.5" x2="429.5" y1="344.8281" y2="362.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="429.5" x2="290.25" y1="362.8281" y2="362.8281"/><polygon fill="#A80036" points="300.25,358.8281,290.25,362.8281,300.25,366.8281,296.25,362.8281" style="stroke: #A8003
6; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="202.8906" y2="222.8906"/><polygon fill="#A80036" points="274.25,212.8906,278.25,222.8906,282.25,212.8906,278.25,216.8906" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="148.9219" y2="168.9219"/><polygon fill="#A80036" points="274.25,158.9219,278.25,168.9219,282.25,158.9219,278.25,162.9219" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="374.8281" y2="384.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="637" y1="384.8281" y2="384.8281"/><polygon fill="#A80036" points="633,269.875,637,259.875,641,269.875,637,265.875" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="637" x2="637" y1="136.9219" y2="384.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="637
" x2="335.25" y1="136.9219" y2="136.9219"/><polygon fill="#A80036" points="345.25,132.9219,335.25,136.9219,345.25,140.9219,341.25,136.9219" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="221.25" x2="24" y1="136.9219" y2="136.9219"/><polygon fill="#A80036" points="20,255.875,24,265.875,28,255.875,24,259.875" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="24" x2="24" y1="136.9219" y2="396.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="24" x2="278.25" y1="396.8281" y2="396.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="396.8281" y2="416.8281"/><polygon fill="#A80036" points="274.25,406.8281,278.25,416.8281,282.25,406.8281,278.25,410.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="104.9219" y2="124.9219"/><polygon fill="#A80036" points="274.25,114.9219,2
78.25,124.9219,282.25,114.9219,278.25,118.9219" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="553.168" y2="580.6836"/><polygon fill="#A80036" points="274.25,570.6836,278.25,580.6836,282.25,570.6836,278.25,574.6836" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="494.7969" y2="519.1992"/><polygon fill="#A80036" points="274.25,509.1992,278.25,519.1992,282.25,509.1992,278.25,513.1992" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="342.25" x2="408.25" y1="482.7969" y2="482.7969"/><polygon fill="#A80036" points="404.25,550.6836,408.25,560.6836,412.25,550.6836,408.25,554.6836" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="408.25" x2="408.25" y1="482.7969" y2="622.6836"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="408.25" x2="2
78.25" y1="622.6836" y2="622.6836"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="622.6836" y2="642.6836"/><polygon fill="#A80036" points="274.25,632.6836,278.25,642.6836,282.25,632.6836,278.25,636.6836" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="450.7969" y2="470.7969"/><polygon fill="#A80036" points="274.25,460.7969,278.25,470.7969,282.25,460.7969,278.25,464.7969" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="666.6836" y2="691.0859"/><polygon fill="#A80036" points="274.25,681.0859,278.25,691.0859,282.25,681.0859,278.25,685.0859" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="377.25" x2="400.75" y1="654.6836" y2="654.6836"/><polygon fill="#A80036" points="396.75,698.0703,400.75,708.0703,404.75,698.0703,400.75,702.0703" style="stroke: #A80036; st
roke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="400.75" x2="400.75" y1="654.6836" y2="757.0547"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="400.75" x2="290.25" y1="757.0547" y2="757.0547"/><polygon fill="#A80036" points="300.25,753.0547,290.25,757.0547,300.25,761.0547,296.25,757.0547" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="725.0547" y2="745.0547"/><polygon fill="#A80036" points="274.25,735.0547,278.25,745.0547,282.25,735.0547,278.25,739.0547" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="769.0547" y2="789.0547"/><polygon fill="#A80036" points="274.25,779.0547,278.25,789.0547,282.25,779.0547,278.25,783.0547" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="278.25" x2="278.25" y1="823.0234" y2="843.0234"/><polygon fill="#A80036" points="274.2
5,833.0234,278.25,843.0234,282.25,833.0234,278.25,837.0234" style="stroke: #A80036; stroke-width: 1.0;"/><!--
+@startuml
+
+title Activity diagram sbws relays exclusion V3BWFile.from_results
+
+start
+:router_statuses_d;
+while (results.items()?)
+ :line, reason = V3BWLine.from_results();
+ if (not reason?) then (yes)
+ :bwlines_raw.append(line);
+ else (no)
+ :bw_lines_excluded.append(line);
+ :exclusion_dict[reason] = exclusion_dict.get(reason, 0) + 1;
+ endif
+endwhile
+:header.add_relays_excluded_counters(exclusion_dict);
+if (not bw_lines_raw?) then (yes)
+ :return (header, bw_lines_excluded);
+ stop
+endif
+if (scaling_method == TORFLOW?) then (yes)
+ :bw_lines = cls.bw_torflow_scale();
+endif
+:return (header, bw_lines + bw_lines_excluded);
+stop
+
+@enduml
+
+PlantUML version 1.2018.13(Mon Nov 26 17:11:51 GMT 2018)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 11.0.9.1+1-post-Debian-1deb10u2
+Operating System: Linux
+OS Version: 4.19.0-13-amd64
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg>
\ No newline at end of file
diff --git a/docs/source/images/activity_aggr_lines.svg b/docs/source/images/activity_aggr_lines.svg
new file mode 100644
index 0000000..789a97b
--- /dev/null
+++ b/docs/source/images/activity_aggr_lines.svg
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="1285px" preserveAspectRatio="none" style="width:430px;height:1285px;" version="1.1" viewBox="0 0 430 1285" width="430px" zoomAndPan="magnify"><defs><filter height="300%" id="fsu3zpce5sdbv" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><text fill="#000000" font-family="sans-serif" font-size="18" lengthAdjust="spacingAndGlyphs" textLength="406" x="12" y="26.708">Activity diagram sbws V3BWLine.from_results</text><ellipse cx="203" cy="40.9531" fill="#000000" filter="url(#fsu3zpce5sdbv)" rx="10" ry
="10" style="stroke: none; stroke-width: 1.0;"/><rect fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="120" x="143" y="70.9531"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="100" x="153" y="92.0918">success_results</text><rect fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="189" x="108.5" y="173.3242"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="169" x="118.5" y="194.4629">return (, exclusion_reason)</text><ellipse cx="203" cy="244.8086" fill="none" filter="url(#fsu3zpce5sdbv)" rx="10" ry="10" style="stroke: #000000; stroke-width: 1.0;"/><ellipse cx="203.5" cy="245.3086" fill="#000000" filter="url(#fsu3zpce5sdbv)" rx="6" ry="6" style="stroke: none; stroke-width: 1.0;"/><polygon fill="#FEFECE" filter=
"url(#fsu3zpce5sdbv)" points="142.5,124.9219,263.5,124.9219,275.5,136.9219,263.5,148.9219,142.5,148.9219,130.5,136.9219,142.5,124.9219" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="207" y="159.1323">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="121" x="142.5" y="140.73">not success_results?</text><rect fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="100" x="153" y="296.8086"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="80" x="163" y="317.9473">results_away</text><rect fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="189" x="108.5" y="399.1797"/><text fill="#000000" font-family="san
s-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="169" x="118.5" y="420.3184">return (, exclusion_reason)</text><ellipse cx="203" cy="470.6641" fill="none" filter="url(#fsu3zpce5sdbv)" rx="10" ry="10" style="stroke: #000000; stroke-width: 1.0;"/><ellipse cx="203.5" cy="471.1641" fill="#000000" filter="url(#fsu3zpce5sdbv)" rx="6" ry="6" style="stroke: none; stroke-width: 1.0;"/><polygon fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" points="151.5,350.7773,254.5,350.7773,266.5,362.7773,254.5,374.7773,151.5,374.7773,139.5,362.7773,151.5,350.7773" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="207" y="384.9878">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="103" x="151.5" y="366.5854">not results_away?</text><rect fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" sty
le="stroke: #A80036; stroke-width: 1.5;" width="110" x="148" y="522.6641"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="90" x="158" y="543.8027">results_recent</text><rect fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="189" x="108.5" y="625.0352"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="169" x="118.5" y="646.1738">return (, exclusion_reason)</text><ellipse cx="203" cy="696.5195" fill="none" filter="url(#fsu3zpce5sdbv)" rx="10" ry="10" style="stroke: #000000; stroke-width: 1.0;"/><ellipse cx="203.5" cy="697.0195" fill="#000000" filter="url(#fsu3zpce5sdbv)" rx="6" ry="6" style="stroke: none; stroke-width: 1.0;"/><polygon fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" points="148,576.6328,258,576.6328,270,588.6328,258,600.6328,148,600.6328,136,588.6328,148,576.6328" style="stroke: #
A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="207" y="610.8433">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="110" x="148" y="592.4409">not results_recent?</text><polygon fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" points="117,748.5195,289,748.5195,301,760.5195,289,772.5195,117,772.5195,105,760.5195,117,748.5195" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="172" x="117" y="764.3276">node_id in router_statuses_d?</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="85" y="757.9253">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="301" y="757.9253">no</text><rect fill="#FEFECE" filter=
"url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="159" x="15.5" y="782.5195"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="139" x="25.5" y="803.6582">consensus_bandwidth</text><rect fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="159" x="231.5" y="782.5195"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="139" x="241.5" y="803.6582">consensus_bandwidth</text><polygon fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" points="203,822.4883,215,834.4883,203,846.4883,191,834.4883,203,822.4883" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="72" x="167" y="866.4883"/><text fill="#000000" font-family="sans-
serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="52" x="177" y="887.627">obs_last</text><rect fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="378" x="14" y="968.8594"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="358" x="24" y="989.998">return(cls(node_id, 1), "no_consensus_no_observed_bw")</text><ellipse cx="203" cy="1040.3438" fill="none" filter="url(#fsu3zpce5sdbv)" rx="10" ry="10" style="stroke: #000000; stroke-width: 1.0;"/><ellipse cx="203.5" cy="1040.8438" fill="#000000" filter="url(#fsu3zpce5sdbv)" rx="6" ry="6" style="stroke: none; stroke-width: 1.0;"/><polygon fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" points="51.5,920.457,354.5,920.457,366.5,932.457,354.5,944.457,51.5,944.457,39.5,932.457,51.5,920.457" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" length
Adjust="spacingAndGlyphs" textLength="20" x="207" y="954.6675">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="303" x="51.5" y="936.2651">obs_last is None and consensus_bandwidth is None?</text><rect fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="37" x="184.5" y="1092.3438"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="17" x="194.5" y="1113.4824">bw</text><rect fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="86" x="160" y="1146.3125"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="66" x="170" y="1167.4512">kwargs[...]</text><rect fill="#FEFECE" filter="url(#fsu3zpce5sdbv)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; st
roke-width: 1.5;" width="252" x="77" y="1200.2813"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="232" x="87" y="1221.4199">return (node_id, bw, **kwargs), None</text><ellipse cx="203" cy="1264.25" fill="none" filter="url(#fsu3zpce5sdbv)" rx="10" ry="10" style="stroke: #000000; stroke-width: 1.0;"/><ellipse cx="203.5" cy="1264.75" fill="#000000" filter="url(#fsu3zpce5sdbv)" rx="6" ry="6" style="stroke: none; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="50.9531" y2="70.9531"/><polygon fill="#A80036" points="199,60.9531,203,70.9531,207,60.9531,203,64.9531" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="207.293" y2="234.8086"/><polygon fill="#A80036" points="199,224.8086,203,234.8086,207,224.8086,203,228.8086" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203"
x2="203" y1="148.9219" y2="173.3242"/><polygon fill="#A80036" points="199,163.3242,203,173.3242,207,163.3242,203,167.3242" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="275.5" x2="307.5" y1="136.9219" y2="136.9219"/><polygon fill="#A80036" points="303.5,204.8086,307.5,214.8086,311.5,204.8086,307.5,208.8086" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="307.5" x2="307.5" y1="136.9219" y2="276.8086"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="307.5" x2="203" y1="276.8086" y2="276.8086"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="276.8086" y2="296.8086"/><polygon fill="#A80036" points="199,286.8086,203,296.8086,207,286.8086,203,290.8086" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="104.9219" y2="124.9219"/><polygon fill="#A80036" points="199,114.9219,203,124.9219,207,114
.9219,203,118.9219" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="433.1484" y2="460.6641"/><polygon fill="#A80036" points="199,450.6641,203,460.6641,207,450.6641,203,454.6641" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="374.7773" y2="399.1797"/><polygon fill="#A80036" points="199,389.1797,203,399.1797,207,389.1797,203,393.1797" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="266.5" x2="307.5" y1="362.7773" y2="362.7773"/><polygon fill="#A80036" points="303.5,430.6641,307.5,440.6641,311.5,430.6641,307.5,434.6641" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="307.5" x2="307.5" y1="362.7773" y2="502.6641"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="307.5" x2="203" y1="502.6641" y2="502.6641"/><line style="stroke: #A80036; stroke-wi
dth: 1.5;" x1="203" x2="203" y1="502.6641" y2="522.6641"/><polygon fill="#A80036" points="199,512.6641,203,522.6641,207,512.6641,203,516.6641" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="330.7773" y2="350.7773"/><polygon fill="#A80036" points="199,340.7773,203,350.7773,207,340.7773,203,344.7773" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="659.0039" y2="686.5195"/><polygon fill="#A80036" points="199,676.5195,203,686.5195,207,676.5195,203,680.5195" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="600.6328" y2="625.0352"/><polygon fill="#A80036" points="199,615.0352,203,625.0352,207,615.0352,203,619.0352" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="270" x2="307.5" y1="588.6328" y2="588.6328"/><polygon fill="#A80036" point
s="303.5,656.5195,307.5,666.5195,311.5,656.5195,307.5,660.5195" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="307.5" x2="307.5" y1="588.6328" y2="728.5195"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="307.5" x2="203" y1="728.5195" y2="728.5195"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="728.5195" y2="748.5195"/><polygon fill="#A80036" points="199,738.5195,203,748.5195,207,738.5195,203,742.5195" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="556.6328" y2="576.6328"/><polygon fill="#A80036" points="199,566.6328,203,576.6328,207,566.6328,203,570.6328" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="105" x2="95" y1="760.5195" y2="760.5195"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="95" x2="95" y1="760.5195" y2="782.5195"/><polygon fill="#A80036" points="91,772.5195
,95,782.5195,99,772.5195,95,776.5195" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="301" x2="311" y1="760.5195" y2="760.5195"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="311" x2="311" y1="760.5195" y2="782.5195"/><polygon fill="#A80036" points="307,772.5195,311,782.5195,315,772.5195,311,776.5195" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="95" x2="95" y1="816.4883" y2="834.4883"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="95" x2="191" y1="834.4883" y2="834.4883"/><polygon fill="#A80036" points="181,830.4883,191,834.4883,181,838.4883,185,834.4883" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="311" x2="311" y1="816.4883" y2="834.4883"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="311" x2="215" y1="834.4883" y2="834.4883"/><polygon fill="#A80036" points="225,830.4883,215,834.4883,225,838.4883,221,
834.4883" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="846.4883" y2="866.4883"/><polygon fill="#A80036" points="199,856.4883,203,866.4883,207,856.4883,203,860.4883" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="1002.8281" y2="1030.3438"/><polygon fill="#A80036" points="199,1020.3438,203,1030.3438,207,1020.3438,203,1024.3438" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="944.457" y2="968.8594"/><polygon fill="#A80036" points="199,958.8594,203,968.8594,207,958.8594,203,962.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="366.5" x2="402" y1="932.457" y2="932.457"/><polygon fill="#A80036" points="398,1000.3438,402,1010.3438,406,1000.3438,402,1004.3438" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80
036; stroke-width: 1.5;" x1="402" x2="402" y1="932.457" y2="1072.3438"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="402" x2="203" y1="1072.3438" y2="1072.3438"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="1072.3438" y2="1092.3438"/><polygon fill="#A80036" points="199,1082.3438,203,1092.3438,207,1082.3438,203,1086.3438" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="900.457" y2="920.457"/><polygon fill="#A80036" points="199,910.457,203,920.457,207,910.457,203,914.457" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="1126.3125" y2="1146.3125"/><polygon fill="#A80036" points="199,1136.3125,203,1146.3125,207,1136.3125,203,1140.3125" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="1180.2813" y2="1200.2813"/><polygon fill="#A80036" points="199,1190
.2813,203,1200.2813,207,1190.2813,203,1194.2813" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="203" x2="203" y1="1234.25" y2="1254.25"/><polygon fill="#A80036" points="199,1244.25,203,1254.25,207,1244.25,203,1248.25" style="stroke: #A80036; stroke-width: 1.0;"/><!--
+@startuml
+
+title Activity diagram sbws V3BWLine.from_results
+
+start
+:success_results;
+if (not success_results?) then (yes)
+ :return (, exclusion_reason);
+ stop
+endif
+:results_away;
+if (not results_away?) then (yes)
+ :return (, exclusion_reason);
+ stop
+endif
+:results_recent;
+if (not results_recent?) then (yes)
+ :return (, exclusion_reason);
+ stop
+endif
+if (node_id in router_statuses_d?) then (yes)
+ :consensus_bandwidth;
+else (no)
+ :consensus_bandwidth;
+endif
+:obs_last;
+if (obs_last is None and consensus_bandwidth is None?) then (yes)
+ :return(cls(node_id, 1), "no_consensus_no_observed_bw");
+ stop
+endif
+:bw;
+:kwargs[...];
+:return (node_id, bw, **kwargs), None;
+stop
+
+@enduml
+
+PlantUML version 1.2018.13(Mon Nov 26 17:11:51 GMT 2018)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 11.0.9.1+1-post-Debian-1deb10u2
+Operating System: Linux
+OS Version: 4.19.0-13-amd64
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg>
\ No newline at end of file
diff --git a/docs/source/images/activity_scaling_as_torflow.svg b/docs/source/images/activity_scaling_as_torflow.svg
new file mode 100644
index 0000000..822bd75
--- /dev/null
+++ b/docs/source/images/activity_scaling_as_torflow.svg
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="1237px" preserveAspectRatio="none" style="width:483px;height:1237px;" version="1.1" viewBox="0 0 483 1237" width="483px" zoomAndPan="magnify"><defs><filter height="300%" id="fq8tw0sgtkabn" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><text fill="#000000" font-family="sans-serif" font-size="18" lengthAdjust="spacingAndGlyphs" textLength="352" x="64.75" y="26.708">Activity diagram sbws bw_torflow_scale</text><ellipse cx="244.5" cy="40.9531" fill="#000000" filter="url(#fq8tw0sgtkabn)" rx="10" ry
="10" style="stroke: none; stroke-width: 1.0;"/><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="276" x="106.5" y="70.9531"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="256" x="116.5" y="92.0918">mu = mean([l.bw_mean for l in bw_lines])</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="260" x="114.5" y="124.9219"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="240" x="124.5" y="146.0605">muf = mean([l.bw_filt for l in bw_lines])</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="95" x="197" y="178.8906"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs"
textLength="75" x="207" y="200.0293">sum_bw = 0</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="66" x="211.5" y="276.8594"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="46" x="221.5" y="297.998">bw_obs</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="396" x="46.5" y="330.8281"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="376" x="56.5" y="351.9668">desc_bw = min(desc_bw_obs, l.desc_bw_bur, l.desc_bw_avg)</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="370" x="59.5" y="384.7969"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="
350" x="69.5" y="405.9355">min_bandwidth = min(desc_bw, l.consensus_bandwidth)</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="213" x="138" y="438.7656"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="193" x="148" y="459.9043">ratio_stream = l.bw_mean / mu</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="247" x="121" y="492.7344"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="227" x="131" y="513.873">ratio_stream_filtered = l.bw_filt / muf</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="318" x="85.5" y="558.7695"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust
="spacingAndGlyphs" textLength="298" x="95.5" y="579.9082">ratio = max(ratio_stream, ratio_stream_filtered)</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="198" x="145.5" y="612.7383"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="178" x="155.5" y="633.877">l.bw = ratio * min_bandwidth</text><polygon fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" points="189.5,666.707,299.5,666.707,311.5,678.707,299.5,690.707,189.5,690.707,177.5,678.707,189.5,666.707" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="110" x="189.5" y="682.5151">router_statuses_d?</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="157.5" y="676.1128">yes</text><text fill="#000000" font-family="sans-serif
" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="311.5" y="676.1128">no</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="121" x="87" y="749.1094"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="101" x="97" y="770.248">sum_bw += l.bw</text><polygon fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" points="58,700.707,237,700.707,249,712.707,237,724.707,58,724.707,46,712.707,58,700.707" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="151.5" y="734.9175">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="179" x="58" y="716.5151">l.node_id in router_statuses_d?</text><polygon fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" points="147.5,803.0781,159.5,815.078
1,147.5,827.0781,135.5,815.0781,147.5,803.0781" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="121" x="281" y="700.707"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="101" x="291" y="721.8457">sum_bw += l.bw</text><polygon fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" points="244.5,833.0781,256.5,845.0781,244.5,857.0781,232.5,845.0781,244.5,833.0781" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" points="196.5,232.8594,292.5,232.8594,304.5,244.8594,292.5,256.8594,196.5,256.8594,184.5,244.8594,196.5,232.8594" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="96" x="196.5" y="248.6675">for l in bw_lines?</text><rect fill="#FEFECE" filter="url(#fq8
tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="157" x="166" y="899.0781"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="137" x="176" y="920.2168">hlimit = sum_bw * cap</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="199" x="145" y="997.0469"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="179" x="155" y="1018.1855">bw_scaled = min(hlimit, l.bw)</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="402" x="43.5" y="1066.0156"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="382" x="53.5" y="1087.1543">l.bw = kb_round_x_sig_dig(bw_scaled, digits=num_round_dig)</text><polygon fil
l="#FEFECE" filter="url(#fq8tw0sgtkabn)" points="196.5,953.0469,292.5,953.0469,304.5,965.0469,292.5,977.0469,196.5,977.0469,184.5,965.0469,196.5,953.0469" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="96" x="196.5" y="968.855">for l in bw_lines?</text><rect fill="#FEFECE" filter="url(#fq8tw0sgtkabn)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="423" x="33" y="1141.9844"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="403" x="43" y="1163.123">return sorted(bw_lines_tf, key=lambda x: x.bw, reverse=reverse)</text><ellipse cx="244.5" cy="1205.9531" fill="none" filter="url(#fq8tw0sgtkabn)" rx="10" ry="10" style="stroke: #000000; stroke-width: 1.0;"/><ellipse cx="245" cy="1206.4531" fill="#000000" filter="url(#fq8tw0sgtkabn)" rx="6" ry="6" style="stroke: none; stroke-width: 1.0;"/><line
style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="50.9531" y2="70.9531"/><polygon fill="#A80036" points="240.5,60.9531,244.5,70.9531,248.5,60.9531,244.5,64.9531" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="104.9219" y2="124.9219"/><polygon fill="#A80036" points="240.5,114.9219,244.5,124.9219,248.5,114.9219,244.5,118.9219" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="158.8906" y2="178.8906"/><polygon fill="#A80036" points="240.5,168.8906,244.5,178.8906,248.5,168.8906,244.5,172.8906" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="310.8281" y2="330.8281"/><polygon fill="#A80036" points="240.5,320.8281,244.5,330.8281,248.5,320.8281,244.5,324.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1=
"244.5" x2="244.5" y1="364.7969" y2="384.7969"/><polygon fill="#A80036" points="240.5,374.7969,244.5,384.7969,248.5,374.7969,244.5,378.7969" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="418.7656" y2="438.7656"/><polygon fill="#A80036" points="240.5,428.7656,244.5,438.7656,248.5,428.7656,244.5,432.7656" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="472.7344" y2="492.7344"/><polygon fill="#A80036" points="240.5,482.7344,244.5,492.7344,248.5,482.7344,244.5,486.7344" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="526.7031" y2="558.7695"/><polygon fill="#A80036" points="240.5,548.7695,244.5,558.7695,248.5,548.7695,244.5,552.7695" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="592.7383" y2="612.
7383"/><polygon fill="#A80036" points="240.5,602.7383,244.5,612.7383,248.5,602.7383,244.5,606.7383" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="147.5" x2="147.5" y1="724.707" y2="749.1094"/><polygon fill="#A80036" points="143.5,739.1094,147.5,749.1094,151.5,739.1094,147.5,743.1094" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="249" x2="261" y1="712.707" y2="712.707"/><polygon fill="#A80036" points="257,756.0938,261,766.0938,265,756.0938,261,760.0938" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="261" x2="261" y1="712.707" y2="815.0781"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="261" x2="159.5" y1="815.0781" y2="815.0781"/><polygon fill="#A80036" points="169.5,811.0781,159.5,815.0781,169.5,819.0781,165.5,815.0781" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="14
7.5" x2="147.5" y1="783.0781" y2="803.0781"/><polygon fill="#A80036" points="143.5,793.0781,147.5,803.0781,151.5,793.0781,147.5,797.0781" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="177.5" x2="147.5" y1="678.707" y2="678.707"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="147.5" x2="147.5" y1="678.707" y2="700.707"/><polygon fill="#A80036" points="143.5,690.707,147.5,700.707,151.5,690.707,147.5,694.707" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="311.5" x2="341.5" y1="678.707" y2="678.707"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="341.5" x2="341.5" y1="678.707" y2="700.707"/><polygon fill="#A80036" points="337.5,690.707,341.5,700.707,345.5,690.707,341.5,694.707" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="147.5" x2="147.5" y1="827.0781" y2="845.0781"/><line style="stroke: #A80036; stroke-width: 1.5;"
x1="147.5" x2="232.5" y1="845.0781" y2="845.0781"/><polygon fill="#A80036" points="222.5,841.0781,232.5,845.0781,222.5,849.0781,226.5,845.0781" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="341.5" x2="341.5" y1="734.6758" y2="845.0781"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="341.5" x2="256.5" y1="845.0781" y2="845.0781"/><polygon fill="#A80036" points="266.5,841.0781,256.5,845.0781,266.5,849.0781,262.5,845.0781" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="646.707" y2="666.707"/><polygon fill="#A80036" points="240.5,656.707,244.5,666.707,248.5,656.707,244.5,660.707" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="256.8594" y2="276.8594"/><polygon fill="#A80036" points="240.5,266.8594,244.5,276.8594,248.5,266.8594,244.5,270.8594" style="stroke: #A80036; stroke-width: 1.
0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="857.0781" y2="867.0781"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="454.5" y1="867.0781" y2="867.0781"/><polygon fill="#A80036" points="450.5,550.7031,454.5,540.7031,458.5,550.7031,454.5,546.7031" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="454.5" x2="454.5" y1="244.8594" y2="867.0781"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="454.5" x2="304.5" y1="244.8594" y2="244.8594"/><polygon fill="#A80036" points="314.5,240.8594,304.5,244.8594,314.5,248.8594,310.5,244.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="184.5" x2="24" y1="244.8594" y2="244.8594"/><polygon fill="#A80036" points="20,536.7031,24,546.7031,28,536.7031,24,540.7031" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="24" x2="24" y1="244.8594" y2="879.
0781"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="24" x2="244.5" y1="879.0781" y2="879.0781"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="879.0781" y2="899.0781"/><polygon fill="#A80036" points="240.5,889.0781,244.5,899.0781,248.5,889.0781,244.5,893.0781" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="212.8594" y2="232.8594"/><polygon fill="#A80036" points="240.5,222.8594,244.5,232.8594,248.5,222.8594,244.5,226.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="1031.0156" y2="1066.0156"/><polygon fill="#A80036" points="240.5,1056.0156,244.5,1066.0156,248.5,1056.0156,244.5,1060.0156" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="977.0469" y2="997.0469"/><polygon fill="#A80036" points="240.5,987.0469,244.5,997.0469,248.5,
987.0469,244.5,991.0469" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="1099.9844" y2="1109.9844"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="457.5" y1="1109.9844" y2="1109.9844"/><polygon fill="#A80036" points="453.5,1046.5156,457.5,1036.5156,461.5,1046.5156,457.5,1042.5156" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="457.5" x2="457.5" y1="965.0469" y2="1109.9844"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="457.5" x2="304.5" y1="965.0469" y2="965.0469"/><polygon fill="#A80036" points="314.5,961.0469,304.5,965.0469,314.5,969.0469,310.5,965.0469" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="184.5" x2="31.5" y1="965.0469" y2="965.0469"/><polygon fill="#A80036" points="27.5,1032.5156,31.5,1042.5156,35.5,1032.5156,31.5,1036.5156" style="stroke: #A80036; stroke-width: 1.5;"/>
<line style="stroke: #A80036; stroke-width: 1.5;" x1="31.5" x2="31.5" y1="965.0469" y2="1121.9844"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="31.5" x2="244.5" y1="1121.9844" y2="1121.9844"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="1121.9844" y2="1141.9844"/><polygon fill="#A80036" points="240.5,1131.9844,244.5,1141.9844,248.5,1131.9844,244.5,1135.9844" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="933.0469" y2="953.0469"/><polygon fill="#A80036" points="240.5,943.0469,244.5,953.0469,248.5,943.0469,244.5,947.0469" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="244.5" x2="244.5" y1="1175.9531" y2="1195.9531"/><polygon fill="#A80036" points="240.5,1185.9531,244.5,1195.9531,248.5,1185.9531,244.5,1189.9531" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#888888" font-family="sans-serif" font-size="10" lengt
hAdjust="spacingAndGlyphs" textLength="119" x="181.25" y="1224.2354">last updated 2021-01-08</text><!--
+@startuml
+
+title Activity diagram sbws bw_torflow_scale
+
+start
+:mu = mean([l.bw_mean for l in bw_lines]);
+:muf = mean([l.bw_filt for l in bw_lines]);
+:sum_bw = 0;
+while (for l in bw_lines?)
+ :bw_obs;
+ :desc_bw = min(desc_bw_obs, l.desc_bw_bur, l.desc_bw_avg);
+ :min_bandwidth = min(desc_bw, l.consensus_bandwidth);
+ :ratio_stream = l.bw_mean / mu;
+ :ratio_stream_filtered = l.bw_filt / muf;
+ :ratio = max(ratio_stream, ratio_stream_filtered);
+ :l.bw = ratio * min_bandwidth;
+ if (router_statuses_d?) then (yes)
+ if (l.node_id in router_statuses_d?) then (yes)
+ :sum_bw += l.bw;
+ endif
+ else (no)
+ :sum_bw += l.bw;
+ endif
+endwhile
+:hlimit = sum_bw * cap;
+while (for l in bw_lines?)
+ :bw_scaled = min(hlimit, l.bw);
+ :l.bw = kb_round_x_sig_dig(bw_scaled, digits=num_round_dig);
+endwhile
+:return sorted(bw_lines_tf, key=lambda x: x.bw, reverse=reverse);
+stop
+
+footer last updated 2021-01-08
+@enduml
+
+PlantUML version 1.2018.13(Mon Nov 26 17:11:51 GMT 2018)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 11.0.9.1+1-post-Debian-1deb10u2
+Operating System: Linux
+OS Version: 4.19.0-13-amd64
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg>
\ No newline at end of file
1
0

26 Feb '21
commit 6e83258c9282d51358c82eb7fc84232dfebfbde3
Author: juga0 <juga(a)riseup.net>
Date: Thu Feb 18 12:21:50 2021 +0000
fix: doc: Separate Torflow/sbws differences
into a new file.
---
docs/source/differences.rst | 36 ++++++++++++++++++++++++++++++++++++
docs/source/index.rst | 3 ++-
docs/source/torflow_aggr.rst | 35 -----------------------------------
3 files changed, 38 insertions(+), 36 deletions(-)
diff --git a/docs/source/differences.rst b/docs/source/differences.rst
new file mode 100644
index 0000000..6f904e5
--- /dev/null
+++ b/docs/source/differences.rst
@@ -0,0 +1,36 @@
+.. _differences:
+
+Differences between Torflow aggregation and sbws scaling (May 2020)
+-------------------------------------------------------------------
+
+Torflow does not exclude relays because of having "few" measurements or "close"
+to each other for that relay.
+
+If there are not new measurements for a relay, Torflow uses the previous
+calculated bandwidth, instead of the new value::
+
+ # If there is a new sample, let's use it for all but guards
+ if n.measured_at > prev_votes.vote_map[n.idhex].measured_at:
+
+ [snip]
+
+ else:
+ # Reset values. Don't vote/sample this measurement round.
+ n.revert_to_vote(prev_votes.vote_map[n.idhex])
+
+The oldest measurements Toflow seems to take are from 4 weeks ago, while sbws
+oldest measurements are 5 days old::
+
+ GUARD_SAMPLE_RATE = 2*7*24*60*60 # 2wks
+
+ [snip]
+
+ MAX_AGE = 2*GUARD_SAMPLE_RATE
+
+ [snip]
+
+ # old measurements are probably
+ # better than no measurements. We may not
+ # measure hibernating routers for days.
+ # This filter is just to remove REALLY old files
+ if time.time() - timestamp > MAX_AGE:
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 53c3886..85f8591 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -41,12 +41,13 @@ Included in the
documenting
how_works
generator
+ torflow_aggr
+ differences
code_design
state
config
config_tor
sbws
- torflow_aggr
implementation
bandwidth_distribution
tor_bandwidth_files
diff --git a/docs/source/torflow_aggr.rst b/docs/source/torflow_aggr.rst
index bc9420d..e9ae3b6 100644
--- a/docs/source/torflow_aggr.rst
+++ b/docs/source/torflow_aggr.rst
@@ -385,41 +385,6 @@ Per relay scaled bandwidth rounding
Finally, the new scaled bandwidth is expressed in kilobytes and rounded a number
of digits.
-Differences between Torflow aggregation and sbws scaling (May 2020)
--------------------------------------------------------------------
-
-Torflow does not exclude relays because of having "few" measurements or "close"
-to each other for that relay.
-
-If there are not new measurements for a relay, Torflow uses the previous
-calculated bandwidth, instead of the new value::
-
- # If there is a new sample, let's use it for all but guards
- if n.measured_at > prev_votes.vote_map[n.idhex].measured_at:
-
- [snip]
-
- else:
- # Reset values. Don't vote/sample this measurement round.
- n.revert_to_vote(prev_votes.vote_map[n.idhex])
-
-The oldest measurements Toflow seems to take are from 4 weeks ago, while sbws
-oldest measurements are 5 days old::
-
- GUARD_SAMPLE_RATE = 2*7*24*60*60 # 2wks
-
- [snip]
-
- MAX_AGE = 2*GUARD_SAMPLE_RATE
-
- [snip]
-
- # old measurements are probably
- # better than no measurements. We may not
- # measure hibernating routers for days.
- # This filter is just to remove REALLY old files
- if time.time() - timestamp > MAX_AGE:
-
.. _README.spec.txt: https://gitweb.torproject.org/torflow.git/tree/NetworkScanners/BwAuthority/…
.. _PID Controller: https://en.wikipedia.org/wiki/PID_controller
1
0

26 Feb '21
commit a374a65ceb04d279f3285daa826255492cdedaf9
Author: juga0 <juga(a)riseup.net>
Date: Thu Feb 18 12:30:59 2021 +0000
fix: doc: Reorganize Torflow aggregation
- reorganize sections
- add diagrams and links
- add pseudocode
- remove math
- correct statements
So that it's more accurate and easier to understand.
---
docs/source/activity_torflow_aggr.puml | 64 +++
docs/source/activity_torflow_scaling.puml | 168 ++++++++
.../activity_torflow_scaling_simplified.puml | 132 ++++++
.../activity_torflow_scaling_simplified1.puml | 38 ++
docs/source/images/activity_torflow_aggr.svg | 52 +++
docs/source/images/activity_torflow_scaling.svg | 169 ++++++++
.../images/activity_torflow_scaling_simplified.svg | 138 +++++++
.../activity_torflow_scaling_simplified1.svg | 47 +++
docs/source/torflow_aggr.rst | 452 ++++++++++++---------
9 files changed, 1071 insertions(+), 189 deletions(-)
diff --git a/docs/source/activity_torflow_aggr.puml b/docs/source/activity_torflow_aggr.puml
new file mode 100644
index 0000000..92a3f38
--- /dev/null
+++ b/docs/source/activity_torflow_aggr.puml
@@ -0,0 +1,64 @@
+@startuml
+title "Activity diagram Torflow measurements aggregation."
+
+' Constants in consensus
+' :Wbd=0 Wbe=0 Wbg=4148 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 Wem=10000 Wgb=10000 Wgd=0 Wgg=5852 Wgm=5852 Wmb=10000 Wmd=0 Wme=0 Wmg=4148 Wmm=10000;
+' Constants in code
+' ;IGNORE_GUARD = 0 GUARD_SAMPLE_RATE = 2*7*24*60*60 # 2wks MAX_AGE = 2*GUARD_SAMPLE_RATE;
+' ;K_p = 1.0 T_i =0 T_i_decay = 0 T_d = 0;
+' Initialization ConsensusJunk
+' :self.bwauth_pid_control = True
+' self.group_by_class = False
+' self.use_pid_tgt = False
+' self.use_circ_fails = False
+' self.use_best_ratio = True
+' self.use_desc_bw = True
+' self.use_mercy = False
+' self.guard_sample_rate = GUARD_SAMPLE_RATE
+' self.pid_max = 500.0
+' self.K_p = K_p = 1.0
+' self.T_i = T_i = 0
+' self.T_d = T_d = 0
+' self.T_i_decay = T_i_decay = 0
+' self.K_i = 0 = self.K_i_decay = Kd;
+
+partition "Initialize relays from consensus (prev_consensus)" {
+ :ns_list = c.get_network_status();
+ 'some ordering i don't understand yet
+ :ns_list.sort(lambda x, y: int(y.bandwidth/10000.0 - x.bandwidth/10000.0));
+
+ :prev_consensus = {};
+ while (for i in range(0, len(ns_list))?)
+ :n = ns_list[i];
+ :n.list_rank = i;
+ :n.measured = False;
+ :prev_consensus["$"+n.idhex] = n;
+ endwhile
+ ' If any relay doesn't have bandwidth, exit
+}
+
+partition "Aggregate raw measurements (nodes)"
+ ' Read measurements
+ :nodes = {};
+ while (for line in bw_file?)
+ if (line.idhex not in nodes?) then (yes)
+ :n = Node();
+ :nodes[line.idhex] = n;
+ :n.add_line(line);
+ endif
+ endwhile
+ ' If not measurements, exit
+}
+
+partition "Assign consensus flags"
+ ' Assign flags (G, M, E) from consensus to measurements
+ while (for idhex in nodes.iterkeys()?)
+ if (idhex in prev_consensus?) then (yes)
+ :nodes[idhex].flags = prev_consensus[idhex].flags;
+ endif
+ endwhile
+}
+
+:scaling;
+
+@enduml
diff --git a/docs/source/activity_torflow_scaling.puml b/docs/source/activity_torflow_scaling.puml
new file mode 100644
index 0000000..7f36f22
--- /dev/null
+++ b/docs/source/activity_torflow_scaling.puml
@@ -0,0 +1,168 @@
+@startuml
+title "Torflow measurements scaling."
+
+' Own previous bwfile
+:prev_votes = VoteSet();
+note right
+initialize measurements from previous Bandwidth File
+end note
+' while (for n in nodes.itervalues()?)
+' if (n.idhex in prev_votes.vote_map and n.idhex in prev_consensus) then (yes)
+' endif
+' endwhile
+:tot_net_bw = 0;
+:;
+note right
+ for every measurement
+end note
+while (for n in nodes.itervalues()?)
+ ' Anything not set is initialized to 0 or None
+ :n.fbw_ratio = n.filt_bw/true_filt_avg[n.node_class()];
+ :n.sbw_ratio = n.strm_bw/true_strm_avg[n.node_class()];
+ :n.use_bw = n.desc_bw;
+ :n.pid_error = ...;
+ note right
+ if n.sbw_ratio > n.fbw_ratio:
+ #assert cs_junk.use_best_ratio == True
+ n.pid_error = (n.strm_bw - true_strm_avg[n.node_class()])
+ / true_strm_avg[n.node_class()]
+ else:
+ n.pid_error = (n.filt_bw - true_filt_avg[n.node_class()])
+ / true_filt_avg[n.node_class()]
+ 0 <= n.pid_error <= 500.0
+ end note
+ if (n.idhex in prev_votes.vote_map?) then (yes)
+ :;
+ note right
+ if n.measured_at >
+ prev_votes.vote_map[n.idhex].measured_at;
+ end note
+ if (measurement newer?) then (yes)
+ :;
+ note right
+ if n.idhex in prev_consensus
+ and ("Guard" in prev_consensus[n.idhex].flags
+ and "Exit" not in prev_consensus[n.idhex].flags)
+ end note
+ if (in prev_consensus, \nis guard \nbut not exit?) then (yes)
+ :;
+ note right
+ if n.idhex not in prev_votes.vote_map
+ or n.measured_at - prev_votes.vote_map[n.idhex].measured_at
+ > cs_junk.guard_sample_rate:
+ # cs_jung.guard_sample_rate = 2*7*24*60*60 # 2wks
+ end note
+ if (diff bigger than 2 weeks) then (yes)
+ :;
+ note right
+ # full feedback
+ n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ cs_junk.K_p,
+ cs_junk.K_i,
+ cs_junk.K_d,
+ cs_junk.K_i_decay)
+ = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ 1.0, 0, 0, 0)
+ end note
+ :self.prev_error = prev_vote.pid_error
+ self.pid_bw = self.use_bw
+ + self.use_bw * self.pid_error
+ # + self.desc_bw * self.pid_error
+ self.pid_error_sum = 0 + self.pid_error
+ n.new_bw = self.pid_bw;
+ else (no)
+ :;
+ note right
+ \# Use new measurement but not feedback
+ n.copy_vote(prev_vote.vote_map[n.idhex]));
+ n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ cs_junk.K_p,
+ cs_junk.K_i,
+ cs_junk.K_d,
+ 0.0, False)
+ end note
+ :\# self.new_bw = vote.bw * 1000
+ self.pid_bw = vote.pid_bw
+ self.pid_error_sum = vote.pid_error_sum
+ self.pid_delta = vote.pid_delta
+
+ n.new_bw = self.use_bw + self.use_bw * self_pid_error
+
+ n.measured_at = prev_vote.measured_at
+ n.pid_error = prev_vote.pid_error;
+ endif
+ ' No (G and noE)
+ else (no)
+ if (in prev_consensus, \nis guard and exit) then (yes)
+ :;
+ note right
+ n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ cs_junk.K_p*weight,
+ cs_junk.K_i*weight,
+ cs_junk.K_d*weight,
+ cs_junk.K_i_decay)
+ n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ 1.0*1.0, 0, 0, 0)
+ \# so, same code as for when diff is bigger than 2 weeks
+ end note
+ :self.prev_error = prev_vote.pid_error
+ self.pid_bw = self.use_bw
+ + self.use_bw * self.pid_error
+ # + self.desc_bw * self.pid_error
+ self.pid_error_sum = 0 + self.pid_error
+ n.new_bw = self.pid_bw;
+ else (no)
+ :;
+ note right
+ \#again, same code
+ end note
+ :self.prev_error = prev_vote.pid_error
+ self.pid_bw = self.use_bw
+ + self.use_bw * self.pid_error
+ # + self.desc_bw * self.pid_error
+ self.pid_error_sum = 0 + self.pid_error
+ n.new_bw = self.pid_bw;
+ endif
+ endif
+ ' No new measurement (in prev bwfile, but havent check consensus), do not vote this round
+ else (no)
+ :;
+ note right
+ \# Reset values. Don't vote/sample this measurement round.
+ \# is in the previous bwfile, but haven't check the consensus
+ n.revert_to_vote(prev_votes.vote_map[n.idhex])
+ \# which calls again self.copy_vote(vote)
+ end note
+ :self.new_bw = prev_vote.bw*1000
+ self.pid_bw = prev_vote.pid_bw
+ self.pid_error_sum = prev_vote.pid_error_sum
+ self.pid_delta = prev_vote.pid_delta
+
+ self.pid_error = vote.pid_error
+ self.measured_at = vote.measured_at;
+
+ endif
+ ' Not in previous bwfile, usually only with authoritites, possibly not in conensus?
+ else (no)
+ ' :n.new_bw = n.use_bw + cs_junk.K_p*n.use_bw*n.pid_error = \n
+ :n.new_bw = n.use_bw + n.use_bw * n.pid_error
+ n.pid_error_sum = n.pid_error
+ n.pid_bw = n.new_bw;
+ endif
+ ' :n.change = n.new_bw - n.desc_bw;
+
+ ' For capping later
+ if (n.idhex in prev_consensus) then (yes)
+ if (prev_consensus[n.idhex].bandwidth != None) then (yes)
+ :prev_consensus[n.idhex].measured = True;
+ :tot_net_bw += n.new_bw;
+ endif
+ endif
+endwhile
+while (for n in nodes.itervalues()?)
+ :cap...;
+endwhile
+stop
+
+footer last updated 2021-01-08
+@enduml
diff --git a/docs/source/activity_torflow_scaling_simplified.puml b/docs/source/activity_torflow_scaling_simplified.puml
new file mode 100644
index 0000000..c52dd09
--- /dev/null
+++ b/docs/source/activity_torflow_scaling_simplified.puml
@@ -0,0 +1,132 @@
+@startuml
+title "Torflow measurements scaling with PID control (Per relay scaled bandwidth)."
+
+' Own previous bwfile
+:prev_votes = VoteSet();
+note right
+initialize measurements from previous Bandwidth File
+end note
+:tot_net_bw = 0;
+:;
+note right
+ for every measurement
+end note
+while (for n in nodes.itervalues()?)
+ partition "Intialize ratios and pid_error" {
+ ' Anything not set is initialized to 0 or None
+ :n.fbw_ratio = n.filt_bw/true_filt_avg[n.node_class()];
+ :n.sbw_ratio = n.strm_bw/true_strm_avg[n.node_class()];
+ :n.use_bw = n.desc_bw;
+ :n.pid_error = max(bwstrm_i / bwstrm, bwfilt_i / bwfilt) - 1;
+ note right
+ if n.sbw_ratio > n.fbw_ratio:
+ #assert cs_junk.use_best_ratio == True
+ n.pid_error = (n.strm_bw - true_strm_avg[n.node_class()])
+ / true_strm_avg[n.node_class()]
+ else:
+ n.pid_error = (n.filt_bw - true_filt_avg[n.node_class()])
+ / true_filt_avg[n.node_class()]
+ 0 <= n.pid_error <= 500.0
+ end note
+ }
+ if (n.idhex in prev_votes.vote_map?) then (yes)
+ :;
+ note right
+ if n.measured_at >
+ prev_votes.vote_map[n.idhex].measured_at;
+ end note
+ if (measurement newer?) then (yes)
+ :;
+ note right
+ if n.idhex in prev_consensus
+ and ("Guard" in prev_consensus[n.idhex].flags=
+ end note
+ if (in prev_consensus, \nis guard?) then (yes)
+ :;
+ note right
+ if n.idhex not in prev_votes.vote_map
+ or n.measured_at - prev_votes.vote_map[n.idhex].measured_at
+ > cs_junk.guard_sample_rate:
+ # cs_jung.guard_sample_rate = 2*7*24*60*60 # 2wks
+ end note
+ if (not exit diff NOT bigger than 2 weeks) then (yes)
+ :;
+ note right
+ \# Use new measurement but not feedback
+ n.copy_vote(prev_vote.vote_map[n.idhex]));
+ n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ cs_junk.K_p,
+ cs_junk.K_i,
+ cs_junk.K_d,
+ 0.0, False)
+ end note
+ :\# self.new_bw = vote.bw * 1000
+ self.pid_bw = vote.pid_bw
+ self.pid_error_sum = vote.pid_error_sum
+ self.pid_delta = vote.pid_delta
+
+ n.new_bw = self.use_bw + self.use_bw * self_pid_error
+
+ n.measured_at = prev_vote.measured_at
+ n.pid_error = prev_vote.pid_error;
+ else (no)
+ :;
+ note right
+ # full feedback
+ n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ cs_junk.K_p,
+ cs_junk.K_i,
+ cs_junk.K_d,
+ cs_junk.K_i_decay)
+ = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ 1.0, 0, 0, 0)
+ end note
+ :self.prev_error = prev_vote.pid_error
+ self.pid_bw = self.use_bw
+ + self.use_bw * self.pid_error
+ # + self.desc_bw * self.pid_error
+ self.pid_error_sum = 0 + self.pid_error
+ n.new_bw = self.pid_bw;
+ endif
+ endif
+ ' No new measurement (in prev bwfile, but havent check consensus), do not vote this round
+ else (no)
+ :;
+ note right
+ \# Reset values. Don't vote/sample this measurement round.
+ \# is in the previous bwfile, but haven't check the consensus
+ n.revert_to_vote(prev_votes.vote_map[n.idhex])
+ \# which calls again self.copy_vote(vote)
+ end note
+ :self.new_bw = prev_vote.bw*1000
+ self.pid_bw = prev_vote.pid_bw
+ self.pid_error_sum = prev_vote.pid_error_sum
+ self.pid_delta = prev_vote.pid_delta
+
+ self.pid_error = vote.pid_error
+ self.measured_at = vote.measured_at;
+
+ endif
+ ' Not in previous bwfile, usually only with authoritites, possibly not in conensus?
+ else (no)
+ ' :n.new_bw = n.use_bw + cs_junk.K_p*n.use_bw*n.pid_error = \n
+ :n.new_bw = n.use_bw + n.use_bw * n.pid_error
+ n.pid_error_sum = n.pid_error
+ n.pid_bw = n.new_bw;
+ endif
+ ' :n.change = n.new_bw - n.desc_bw;
+
+ ' For capping later
+ if (n.idhex in prev_consensus) then (yes)
+ if (prev_consensus[n.idhex].bandwidth != None) then (yes)
+ :prev_consensus[n.idhex].measured = True;
+ :tot_net_bw += n.new_bw;
+ endif
+ endif
+endwhile
+while (for n in nodes.itervalues()?)
+ :cap...;
+endwhile
+stop
+
+@enduml
diff --git a/docs/source/activity_torflow_scaling_simplified1.puml b/docs/source/activity_torflow_scaling_simplified1.puml
new file mode 100644
index 0000000..b32b30d
--- /dev/null
+++ b/docs/source/activity_torflow_scaling_simplified1.puml
@@ -0,0 +1,38 @@
+@startuml
+title "Torflow measurements scaling with PID control (Per relay scaled bandwidth)."
+
+' Own previous bwfile
+:prev_votes = VoteSet();
+:tot_net_bw = 0;
+:;
+note right
+ for every measurement
+end note
+while (for n in nodes.itervalues()?)
+ partition "Intialize ratios and pid_error" {
+ ' Anything not set is initialized to 0 or None
+ :n.fbw_ratio = n.filt_bw/true_filt_avg[n.node_class()];
+ :n.sbw_ratio = n.strm_bw/true_strm_avg[n.node_class()];
+ :n.use_bw = n.desc_bw;
+ :n.pid_error = max(n.fbw_ratio, n.sbw_ratio) - 1;
+ }
+ if (n.idhex in prev_votes.vote_map \nand not newer measurement?) then (yes)
+ :self.new_bw = prev_vote.bw*1000
+ self.measured_at = vote.measured_at;
+ ' Not in previous bwfile, usually only with authoritites, possibly not in conensus?
+ else (no)
+ :n.new_bw = n.use_bw + n.use_bw * n.pid_error;
+ endif
+
+ ' For capping later
+ if (n.idhex in prev_consensus \nand prev_consensus[n.idhex].bandwidth != None) then (yes)
+ :prev_consensus[n.idhex].measured = True
+ tot_net_bw += n.new_bw;
+ endif
+endwhile
+while (for n in nodes.itervalues()?)
+ :cap...;
+endwhile
+stop
+
+@enduml
diff --git a/docs/source/images/activity_torflow_aggr.svg b/docs/source/images/activity_torflow_aggr.svg
new file mode 100644
index 0000000..f672ae7
--- /dev/null
+++ b/docs/source/images/activity_torflow_aggr.svg
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="1241px" preserveAspectRatio="none" style="width:517px;height:1241px;" version="1.1" viewBox="0 0 517 1241" width="517px" zoomAndPan="magnify"><defs><filter height="300%" id="fz6rz3k2gra6i" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><text fill="#000000" font-family="sans-serif" font-size="18" lengthAdjust="spacingAndGlyphs" textLength="490" x="12.5" y="26.708">"Activity diagram Torflow measurements aggregation."</text><rect fill="#FFFFFF" filter="url(#fz6rz3k2gra6i)" height="480.0781" style=
"stroke: #000000; stroke-width: 2.0;" width="496" x="10" y="31.7549"/><path d="M362,32.7549 L362,41.0518 L352,51.0518 L10,51.0518 " fill="none" style="stroke: #000000; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="342" x="13" y="45.75">Initialize relays from consensus (prev_consensus)</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="221" x="147.5" y="61.0518"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="201" x="157.5" y="82.1904">ns_list = c.get_network_status()</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="476" x="20" y="115.0205"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="456" x="30" y="136.
1592">ns_list.sort(lambda x, y: int(y.bandwidth/10000.0 - x.bandwidth/10000.0))</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="155" x="180.5" y="168.9893"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="135" x="190.5" y="190.1279">prev_consensus = {}</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="98" x="209" y="266.958"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="78" x="219" y="288.0967">n = ns_list[i]</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="105" x="205.5" y="320.9268"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength=
"85" x="215.5" y="342.0654">n.list_rank = i</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="146" x="185" y="389.8955"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="126" x="195" y="411.0342">n.measured = False</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="230" x="143" y="443.8643"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="210" x="153" y="465.0029">prev_consensus["$"+n.idhex] = n</text><polygon fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" points="175.5,222.958,340.5,222.958,352.5,234.958,340.5,246.958,175.5,246.958,163.5,234.958,175.5,222.958" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGl
yphs" textLength="165" x="175.5" y="238.7661">for i in range(0, len(ns_list))?</text><rect fill="#FFFFFF" filter="url(#fz6rz3k2gra6i)" height="402.5742" style="stroke: #000000; stroke-width: 2.0;" width="287" x="119" y="522.6348"/><path d="M396,523.6348 L396,531.9316 L386,541.9316 L119,541.9316 " fill="none" style="stroke: #000000; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="267" x="122" y="536.6299">Aggregate raw measurements (nodes)</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="93" x="211.5" y="558.9316"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="73" x="221.5" y="580.0703">nodes = {}</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="89" x="213.5" y="
705.3027"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="69" x="223.5" y="726.4414">n = Node()</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="154" x="181" y="759.2715"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="134" x="191" y="780.4102">nodes[line.idhex] = n</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="116" x="200" y="813.2402"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="96" x="210" y="834.3789">n.add_line(line)</text><polygon fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" points="190.5,656.9004,325.5,656.9004,337.5,668.9004,325.5,680.9004,190.5,680.9004,178.5,668.9004,190.5,656.9004" style="stroke: #A80036; stro
ke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="262" y="691.1108">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="135" x="190.5" y="672.7085">line.idhex not in nodes?</text><polygon fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" points="258,867.209,270,879.209,258,891.209,246,879.209,258,867.209" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" points="206.5,612.9004,309.5,612.9004,321.5,624.9004,309.5,636.9004,206.5,636.9004,194.5,624.9004,206.5,612.9004" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="103" x="206.5" y="628.7085">for line in bw_file?</text><rect fill="#FFFFFF" filter="url(#fz6rz3k2gra6i)" height="240.668" style="stroke: #000000; stroke-width: 2.0;" width="429" x="48" y="936.
0107"/><path d="M221,937.0107 L221,945.3076 L211,955.3076 L48,955.3076 " fill="none" style="stroke: #000000; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="163" x="51" y="950.0059">Assign consensus flags</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="332" x="92" y="1064.71"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="312" x="102" y="1085.8486">nodes[idhex].flags = prev_consensus[idhex].flags</text><polygon fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" points="184.5,1016.3076,331.5,1016.3076,343.5,1028.3076,331.5,1040.3076,184.5,1040.3076,172.5,1028.3076,184.5,1016.3076" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="262" y="1050.5181">yes</tex
t><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="147" x="184.5" y="1032.1157">idhex in prev_consensus?</text><polygon fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" points="258,1118.6787,270,1130.6787,258,1142.6787,246,1130.6787,258,1118.6787" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" points="175,972.3076,341,972.3076,353,984.3076,341,996.3076,175,996.3076,163,984.3076,175,972.3076" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="166" x="175" y="988.1157">for idhex in nodes.iterkeys()?</text><rect fill="#FEFECE" filter="url(#fz6rz3k2gra6i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="64" x="226" y="1196.6787"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="44" x="236" y="12
17.8174">scaling</text><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="95.0205" y2="115.0205"/><polygon fill="#A80036" points="254,105.0205,258,115.0205,262,105.0205,258,109.0205" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="148.9893" y2="168.9893"/><polygon fill="#A80036" points="254,158.9893,258,168.9893,262,158.9893,258,162.9893" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="300.9268" y2="320.9268"/><polygon fill="#A80036" points="254,310.9268,258,320.9268,262,310.9268,258,314.9268" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="354.8955" y2="389.8955"/><polygon fill="#A80036" points="254,379.8955,258,389.8955,262,379.8955,258,383.8955" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258"
y1="423.8643" y2="443.8643"/><polygon fill="#A80036" points="254,433.8643,258,443.8643,262,433.8643,258,437.8643" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="246.958" y2="266.958"/><polygon fill="#A80036" points="254,256.958,258,266.958,262,256.958,258,260.958" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="477.833" y2="487.833"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="385" y1="487.833" y2="487.833"/><polygon fill="#A80036" points="381,370.3955,385,360.3955,389,370.3955,385,366.3955" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="385" x2="385" y1="234.958" y2="487.833"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="385" x2="352.5" y1="234.958" y2="234.958"/><polygon fill="#A80036" points="362.5,230.958,352.5,234.958,362.5,238.958,358.5,234.958" style="stroke:
#A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="163.5" x2="131" y1="234.958" y2="234.958"/><polygon fill="#A80036" points="127,356.3955,131,366.3955,135,356.3955,131,360.3955" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="131" x2="131" y1="234.958" y2="499.833"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="131" x2="258" y1="499.833" y2="499.833"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="499.833" y2="558.9316"/><polygon fill="#A80036" points="254,548.9316,258,558.9316,262,548.9316,258,552.9316" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="202.958" y2="222.958"/><polygon fill="#A80036" points="254,212.958,258,222.958,262,212.958,258,216.958" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="739.2715" y2="759.2715"/><polyg
on fill="#A80036" points="254,749.2715,258,759.2715,262,749.2715,258,753.2715" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="793.2402" y2="813.2402"/><polygon fill="#A80036" points="254,803.2402,258,813.2402,262,803.2402,258,807.2402" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="680.9004" y2="705.3027"/><polygon fill="#A80036" points="254,695.3027,258,705.3027,262,695.3027,258,699.3027" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="337.5" x2="349.5" y1="668.9004" y2="668.9004"/><polygon fill="#A80036" points="345.5,766.2559,349.5,776.2559,353.5,766.2559,349.5,770.2559" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.5" x2="349.5" y1="668.9004" y2="879.209"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.5" x2="270" y1="879.20
9" y2="879.209"/><polygon fill="#A80036" points="280,875.209,270,879.209,280,883.209,276,879.209" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="847.209" y2="867.209"/><polygon fill="#A80036" points="254,857.209,258,867.209,262,857.209,258,861.209" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="636.9004" y2="656.9004"/><polygon fill="#A80036" points="254,646.9004,258,656.9004,262,646.9004,258,650.9004" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="891.209" y2="901.209"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="369" y1="901.209" y2="901.209"/><polygon fill="#A80036" points="365,774.2559,369,764.2559,373,774.2559,369,770.2559" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="369" x2="369" y1="624.9004" y2="
901.209"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="369" x2="321.5" y1="624.9004" y2="624.9004"/><polygon fill="#A80036" points="331.5,620.9004,321.5,624.9004,331.5,628.9004,327.5,624.9004" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="194.5" x2="159" y1="624.9004" y2="624.9004"/><polygon fill="#A80036" points="155,760.2559,159,770.2559,163,760.2559,159,764.2559" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="159" x2="159" y1="624.9004" y2="913.209"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="159" x2="258" y1="913.209" y2="913.209"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="913.209" y2="972.3076"/><polygon fill="#A80036" points="254,962.3076,258,972.3076,262,962.3076,258,966.3076" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="592.9004" y2="612.9004"/><polygo
n fill="#A80036" points="254,602.9004,258,612.9004,262,602.9004,258,606.9004" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="1040.3076" y2="1064.71"/><polygon fill="#A80036" points="254,1054.71,258,1064.71,262,1054.71,258,1058.71" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="343.5" x2="434" y1="1028.3076" y2="1028.3076"/><polygon fill="#A80036" points="430,1071.6943,434,1081.6943,438,1071.6943,434,1075.6943" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="434" x2="434" y1="1028.3076" y2="1130.6787"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="434" x2="270" y1="1130.6787" y2="1130.6787"/><polygon fill="#A80036" points="280,1126.6787,270,1130.6787,280,1134.6787,276,1130.6787" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="1098.6787" y
2="1118.6787"/><polygon fill="#A80036" points="254,1108.6787,258,1118.6787,262,1108.6787,258,1112.6787" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="996.3076" y2="1016.3076"/><polygon fill="#A80036" points="254,1006.3076,258,1016.3076,262,1006.3076,258,1010.3076" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="1142.6787" y2="1152.6787"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="458" y1="1152.6787" y2="1152.6787"/><polygon fill="#A80036" points="454,1079.6943,458,1069.6943,462,1079.6943,458,1075.6943" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="458" x2="458" y1="984.3076" y2="1152.6787"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="458" x2="353" y1="984.3076" y2="984.3076"/><polygon fill="#A80036" points="363,980.3076,353,984.3076,363,988.3076,359,984.3076" styl
e="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="163" x2="70" y1="984.3076" y2="984.3076"/><polygon fill="#A80036" points="66,1065.6943,70,1075.6943,74,1065.6943,70,1069.6943" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="70" x2="70" y1="984.3076" y2="1164.6787"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="70" x2="258" y1="1164.6787" y2="1164.6787"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="258" x2="258" y1="1164.6787" y2="1196.6787"/><polygon fill="#A80036" points="254,1186.6787,258,1196.6787,262,1186.6787,258,1190.6787" style="stroke: #A80036; stroke-width: 1.0;"/><!--
+@startuml
+title "Activity diagram Torflow measurements aggregation."
+
+
+partition "Initialize relays from consensus (prev_consensus)" {
+ :ns_list = c.get_network_status();
+ :ns_list.sort(lambda x, y: int(y.bandwidth/10000.0 - x.bandwidth/10000.0));
+
+ :prev_consensus = {};
+ while (for i in range(0, len(ns_list))?)
+ :n = ns_list[i];
+ :n.list_rank = i;
+ :n.measured = False;
+ :prev_consensus["$"+n.idhex] = n;
+ endwhile
+}
+
+partition "Aggregate raw measurements (nodes)"
+ :nodes = {};
+ while (for line in bw_file?)
+ if (line.idhex not in nodes?) then (yes)
+ :n = Node();
+ :nodes[line.idhex] = n;
+ :n.add_line(line);
+ endif
+ endwhile
+}
+
+partition "Assign consensus flags"
+ while (for idhex in nodes.iterkeys()?)
+ if (idhex in prev_consensus?) then (yes)
+ :nodes[idhex].flags = prev_consensus[idhex].flags;
+ endif
+ endwhile
+}
+
+:scaling;
+
+@enduml
+
+PlantUML version 1.2018.13(Mon Nov 26 17:11:51 GMT 2018)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 11.0.9.1+1-post-Debian-1deb10u2
+Operating System: Linux
+OS Version: 4.19.0-13-amd64
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg>
\ No newline at end of file
diff --git a/docs/source/images/activity_torflow_scaling.svg b/docs/source/images/activity_torflow_scaling.svg
new file mode 100644
index 0000000..c9cb6c4
--- /dev/null
+++ b/docs/source/images/activity_torflow_scaling.svg
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="1850px" preserveAspectRatio="none" style="width:3144px;height:1850px;" version="1.1" viewBox="0 0 3144 1850" width="3144px" zoomAndPan="magnify"><defs><filter height="300%" id="f9dswc3p3ycf8" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><text fill="#000000" font-family="sans-serif" font-size="18" lengthAdjust="spacingAndGlyphs" textLength="292" x="1425.2188" y="26.708">"Torflow measurements scaling."</text><path d="M2421.5,35.3711 L2421.5,43.9375 L2401.5,47.9375 L2421.5,51.9375 L2421.5,60.503
9 A0,0 0 0 0 2421.5,60.5039 L2782.5,60.5039 A0,0 0 0 0 2782.5,60.5039 L2782.5,45.3711 L2772.5,35.3711 L2421.5,35.3711 A0,0 0 0 0 2421.5,35.3711 " fill="#FBFB77" filter="url(#f9dswc3p3ycf8)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M2772.5,35.3711 L2772.5,45.3711 L2782.5,45.3711 L2772.5,35.3711 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="340" x="2427.5" y="52.438">initialize measurements from previous Bandwidth File</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="165" x="2236.5" y="30.9531"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="145" x="2246.5" y="52.0918">prev_votes = VoteSet()</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A800
36; stroke-width: 1.5;" width="114" x="2262" y="84.9219"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="94" x="2272" y="106.0605">tot_net_bw = 0</text><path d="M2351,143.3086 L2351,151.875 L2331,155.875 L2351,159.875 L2351,168.4414 A0,0 0 0 0 2351,168.4414 L2523,168.4414 A0,0 0 0 0 2523,168.4414 L2523,153.3086 L2513,143.3086 L2351,143.3086 A0,0 0 0 0 2351,143.3086 " fill="#FBFB77" filter="url(#f9dswc3p3ycf8)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M2513,143.3086 L2513,153.3086 L2523,153.3086 L2513,143.3086 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="151" x="2357" y="160.3755">for every measurement</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="2307" y="138.8906"/><text fill="#000000" fon
t-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="2321" y="160.0293"/><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="337" x="2150.5" y="236.8594"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="317" x="2160.5" y="257.998">n.fbw_ratio = n.filt_bw/true_filt_avg[n.node_class()]</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="366" x="2136" y="290.8281"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="346" x="2146" y="311.9668">n.sbw_ratio = n.strm_bw/true_strm_avg[n.node_class()]</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="161" x="2238.5" y="344.7969"/><te
xt fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="141" x="2248.5" y="365.9355">n.use_bw = n.desc_bw</text><path d="M2398,388.7656 L2398,450.2969 L2378,454.2969 L2398,458.2969 L2398,519.8281 A0,0 0 0 0 2398,519.8281 L2792,519.8281 A0,0 0 0 0 2792,519.8281 L2792,398.7656 L2782,388.7656 L2398,388.7656 A0,0 0 0 0 2398,388.7656 " fill="#FBFB77" filter="url(#f9dswc3p3ycf8)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M2782,388.7656 L2782,398.7656 L2792,398.7656 L2782,388.7656 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="175" x="2404" y="405.8325">if n.sbw_ratio > n.fbw_ratio:</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="12" x="2404" y="420.9653">1.</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGl
yphs" textLength="247" x="2420" y="420.9653">assert cs_junk.use_best_ratio == True</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="373" x="2404" y="436.0981">n.pid_error = (n.strm_bw - true_strm_avg[n.node_class()])</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="204" x="2484" y="451.231">/ true_strm_avg[n.node_class()]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="30" x="2404" y="466.3638">else:</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="343" x="2404" y="481.4966">n.pid_error = (n.filt_bw - true_filt_avg[n.node_class()])</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="189" x="2484" y="496.6294">/ true_filt_avg[n.node_class()]</text><text fill="#000000" font-family="
sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="173" x="2404" y="511.7622">0 <= n.pid_error <= 500.0</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="118" x="2260" y="437.3125"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="98" x="2270" y="458.4512">n.pid_error = ...</text><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="2226,539.8281,2412,539.8281,2424,551.8281,2412,563.8281,2226,563.8281,2214,551.8281,2226,539.8281" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="186" x="2226" y="555.6362">n.idhex in prev_votes.vote_map?</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="2194" y="549.2339">yes</text><text fill="#000000" fon
t-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="2424" y="549.2339">no</text><path d="M1725.125,573.8281 L1725.125,589.9609 L1705.125,593.9609 L1725.125,597.9609 L1725.125,614.0938 A0,0 0 0 0 1725.125,614.0938 L2033.125,614.0938 A0,0 0 0 0 2033.125,614.0938 L2033.125,583.8281 L2023.125,573.8281 L1725.125,573.8281 A0,0 0 0 0 1725.125,573.8281 " fill="#FBFB77" filter="url(#f9dswc3p3ycf8)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M2023.125,573.8281 L2023.125,583.8281 L2033.125,583.8281 L2023.125,573.8281 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="123" x="1731.125" y="590.895">if n.measured_at ></text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="287" x="1731.125" y="606.0278">prev_votes.vote_map[n.idhex].measured_at;</text><rect fill="#FEFECE" filter="
url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="1681.125" y="576.9766"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="1695.125" y="598.1152"/><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="1630.625,649.0938,1755.625,649.0938,1767.625,661.0938,1755.625,673.0938,1630.625,673.0938,1618.625,661.0938,1630.625,649.0938" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="125" x="1630.625" y="664.9019">measurement newer?</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="1598.625" y="658.4995">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="1767.625" y="658.4995">no</text><path d="M1100.25,683.0938 L1100.25,706
.793 L1080.25,710.793 L1100.25,714.793 L1100.25,738.4922 A0,0 0 0 0 1100.25,738.4922 L1440.25,738.4922 A0,0 0 0 0 1440.25,738.4922 L1440.25,693.0938 L1430.25,683.0938 L1100.25,683.0938 A0,0 0 0 0 1100.25,683.0938 " fill="#FBFB77" filter="url(#f9dswc3p3ycf8)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M1430.25,683.0938 L1430.25,693.0938 L1440.25,693.0938 L1430.25,683.0938 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="179" x="1106.25" y="700.1606">if n.idhex in prev_consensus</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="294" x="1122.25" y="715.2935">and ("Guard" in prev_consensus[n.idhex].flags</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="303" x="1122.25" y="730.4263">and "Exit" not in prev_consensus[n.idhex].flags)</text><re
ct fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="1056.25" y="693.8086"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="1070.25" y="714.9473"/><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="1010.75,773.4922,1125.75,773.4922,1137.75,792.6992,1125.75,811.9063,1010.75,811.9063,998.75,792.6992,1010.75,773.4922" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="111" x="1010.75" y="783.7026">in prev_consensus,</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="47" x="1010.75" y="796.5073">is guard</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="70" x="1010.75" y="809.312">but not exit?</text><text fill=
"#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="978.75" y="790.105">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="1137.75" y="790.105">no</text><path d="M509,821.9063 L509,853.1719 L489,857.1719 L509,861.1719 L509,892.4375 A0,0 0 0 0 509,892.4375 L956,892.4375 A0,0 0 0 0 956,892.4375 L956,831.9063 L946,821.9063 L509,821.9063 A0,0 0 0 0 509,821.9063 " fill="#FBFB77" filter="url(#f9dswc3p3ycf8)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M946,821.9063 L946,831.9063 L956,831.9063 L946,821.9063 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="239" x="515" y="838.9731">if n.idhex not in prev_votes.vote_map</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="410" x="531" y="854
.106">or n.measured_at - prev_votes.vote_map[n.idhex].measured_at</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="194" x="547" y="869.2388">> cs_junk.guard_sample_rate:</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="352" x="547" y="884.3716"># cs_jung.guard_sample_rate = 2*7*24*60*60 # 2wks</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="465" y="840.1875"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="479" y="861.3262"/><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="408,927.4375,546,927.4375,558,939.4375,546,951.4375,408,951.4375,396,939.4375,408,927.4375" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="sp
acingAndGlyphs" textLength="138" x="408" y="943.2456">diff bigger than 2 weeks</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="376" y="936.8433">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="558" y="936.8433">no</text><path d="M200,961.4375 L200,1022.9688 L180,1026.9688 L200,1030.9688 L200,1092.5 A0,0 0 0 0 200,1092.5 L587,1092.5 A0,0 0 0 0 587,1092.5 L587,971.4375 L577,961.4375 L200,961.4375 A0,0 0 0 0 200,961.4375 " fill="#FBFB77" filter="url(#f9dswc3p3ycf8)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M577,961.4375 L577,971.4375 L587,971.4375 L577,961.4375 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="12" x="206" y="978.5044">1.</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust=
"spacingAndGlyphs" textLength="80" x="222" y="978.5044">full feedback</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="366" x="206" y="993.6372">n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="78" x="270" y="1008.77">cs_junk.K_p,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="73" x="270" y="1023.9028">cs_junk.K_i,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="78" x="270" y="1039.0356">cs_junk.K_d,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="119" x="270" y="1054.1685">cs_junk.K_i_decay)</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="301" x="222" y="1069
.3013">= n.get_pid_bw(prev_votes.vote_map[n.idhex],</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="73" x="282" y="1084.4341">1.0, 0, 0, 0)</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="156" y="1009.9844"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="170" y="1031.123"/><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="103.8125" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="260" x="38" y="1127.5"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="228" x="48" y="1148.6387">self.prev_error = prev_vote.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="158" x="48" y="1162.6074">self.pid_bw = self.use_b
w</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="182" x="64" y="1176.5762">+ self.use_bw * self.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="203" x="64" y="1190.5449"># + self.desc_bw * self.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="240" x="48" y="1204.5137">self.pid_error_sum = 0 + self.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="146" x="48" y="1218.4824">n.new_bw = self.pid_bw</text><path d="M818,961.4375 L818,1015.4023 L798,1019.4023 L818,1023.4023 L818,1077.3672 A0,0 0 0 0 818,1077.3672 L1205,1077.3672 A0,0 0 0 0 1205,1077.3672 L1205,971.4375 L1195,961.4375 L818,961.4375 A0,0 0 0 0 818,961.4375 " fill="#FBFB77" filter="url(#f9dswc3p3ycf8)" style="stroke: #A80036; stroke-width: 1.0;"/><pat
h d="M1195,961.4375 L1195,971.4375 L1205,971.4375 L1195,961.4375 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="280" x="824" y="978.5044">\# Use new measurement but not feedback</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="283" x="824" y="993.6372">n.copy_vote(prev_vote.vote_map[n.idhex]));</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="366" x="824" y="1008.77">n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="78" x="872" y="1023.9028">cs_junk.K_p,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="73" x="872" y="1039.0356">cs_junk.K_i,</text><text fill="#000000" fo
nt-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="78" x="872" y="1054.1685">cs_junk.K_d,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="66" x="872" y="1069.3013">0.0, False)</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="774" y="1002.418"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="788" y="1023.5566"/><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="145.7188" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="358" x="607" y="1112.3672"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="204" x="617" y="1133.5059">\# self.new_bw = vote.bw * 1000</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyp
hs" textLength="159" x="617" y="1147.4746">self.pid_bw = vote.pid_bw</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="251" x="617" y="1161.4434">self.pid_error_sum = vote.pid_error_sum</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="189" x="617" y="1175.4121">self.pid_delta = vote.pid_delta</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="621" y="1189.3809"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="338" x="617" y="1203.3496">n.new_bw = self.use_bw + self.use_bw * self_pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="621" y="1217.3184"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="258" x="617" y=
"1231.2871">n.measured_at = prev_vote.measured_at</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="206" x="617" y="1245.2559">n.pid_error = prev_vote.pid_error</text><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="477,1264.0859,489,1276.0859,477,1288.0859,465,1276.0859,477,1264.0859" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="1602,821.9063,1717,821.9063,1729,834.7109,1717,847.5156,1602,847.5156,1590,834.7109,1602,821.9063" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="111" x="1602" y="832.1167">in prev_consensus,</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="96" x="1602" y="844.9214">is guard and exit</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="
spacingAndGlyphs" textLength="20" x="1570" y="832.1167">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="1729" y="832.1167">no</text><path d="M1407,857.5156 L1407,919.0469 L1387,923.0469 L1407,927.0469 L1407,988.5781 A0,0 0 0 0 1407,988.5781 L1794,988.5781 A0,0 0 0 0 1794,988.5781 L1794,867.5156 L1784,857.5156 L1407,857.5156 A0,0 0 0 0 1407,857.5156 " fill="#FBFB77" filter="url(#f9dswc3p3ycf8)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M1784,857.5156 L1784,867.5156 L1794,867.5156 L1784,857.5156 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="366" x="1413" y="874.5825">n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="126" x="1445" y="889.7153">cs_junk.K_p*weight,</text>
<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="121" x="1445" y="904.8481">cs_junk.K_i*weight,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="126" x="1445" y="919.981">cs_junk.K_d*weight,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="119" x="1445" y="935.1138">cs_junk.K_i_decay)</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="366" x="1413" y="950.2466">n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="100" x="1461" y="965.3794">1.0*1.0, 0, 0, 0)</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="359" x="1413" y="980.5122">\# so, same code as for when diff is bigger t
han 2 weeks</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="1363" y="906.0625"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="1377" y="927.2012"/><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="103.8125" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="260" x="1245" y="1023.5781"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="228" x="1255" y="1044.7168">self.prev_error = prev_vote.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="158" x="1255" y="1058.6855">self.pid_bw = self.use_bw</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="182" x="1271" y="1072.6543">+ self.use_bw * self.pid_error</text><te
xt fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="203" x="1271" y="1086.623"># + self.desc_bw * self.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="240" x="1255" y="1100.5918">self.pid_error_sum = 0 + self.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="146" x="1255" y="1114.5605">n.new_bw = self.pid_bw</text><path d="M1976,861.9336 L1976,870.5 L1956,874.5 L1976,878.5 L1976,887.0664 A0,0 0 0 0 1976,887.0664 L2126,887.0664 A0,0 0 0 0 2126,887.0664 L2126,871.9336 L2116,861.9336 L1976,861.9336 A0,0 0 0 0 1976,861.9336 " fill="#FBFB77" filter="url(#f9dswc3p3ycf8)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M2116,861.9336 L2116,871.9336 L2126,871.9336 L2116,861.9336 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size
="13" lengthAdjust="spacingAndGlyphs" textLength="129" x="1982" y="879.0005">\#again, same code</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="1932" y="857.5156"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="1946" y="878.6543"/><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="103.8125" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="260" x="1814" y="926.4844"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="228" x="1824" y="947.623">self.prev_error = prev_vote.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="158" x="1824" y="961.5918">self.pid_bw = self.use_bw</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs"
textLength="182" x="1840" y="975.5605">+ self.use_bw * self.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="203" x="1840" y="989.5293"># + self.desc_bw * self.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="240" x="1824" y="1003.498">self.pid_error_sum = 0 + self.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="146" x="1824" y="1017.4668">n.new_bw = self.pid_bw</text><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="1659.5,1133.3906,1671.5,1145.3906,1659.5,1157.3906,1647.5,1145.3906,1659.5,1133.3906" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="1068.25,1294.0859,1080.25,1306.0859,1068.25,1318.0859,1056.25,1306.0859,1068.25,1294.0859" style="stroke: #A80036; stroke-width: 1.5;"/><path d="M2347.4375,
683.0938 L2347.4375,714.3594 L2327.4375,718.3594 L2347.4375,722.3594 L2347.4375,753.625 A0,0 0 0 0 2347.4375,753.625 L2760.4375,753.625 A0,0 0 0 0 2760.4375,753.625 L2760.4375,693.0938 L2750.4375,683.0938 L2347.4375,683.0938 A0,0 0 0 0 2347.4375,683.0938 " fill="#FBFB77" filter="url(#f9dswc3p3ycf8)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M2750.4375,683.0938 L2750.4375,693.0938 L2760.4375,693.0938 L2750.4375,683.0938 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="392" x="2353.4375" y="700.1606">\# Reset values. Don't vote/sample this measurement round.</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="384" x="2353.4375" y="715.2935">\# is in the previous bwfile, but haven't check the consensus</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs"
textLength="309" x="2353.4375" y="730.4263">n.revert_to_vote(prev_votes.vote_map[n.idhex])</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="258" x="2353.4375" y="745.5591">\# which calls again self.copy_vote(vote)</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="2303.4375" y="701.375"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="2317.4375" y="722.5137"/><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="117.7813" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="304" x="2163.4375" y="788.625"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="211" x="2173.4375" y="809.7637">self.new_bw = prev_vote.bw*1000</text><text fill="#000000" font-family="sans-serif" font-size="12" len
gthAdjust="spacingAndGlyphs" textLength="192" x="2173.4375" y="823.7324">self.pid_bw = prev_vote.pid_bw</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="284" x="2173.4375" y="837.7012">self.pid_error_sum = prev_vote.pid_error_sum</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="222" x="2173.4375" y="851.6699">self.pid_delta = prev_vote.pid_delta</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="2177.4375" y="865.6387"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="187" x="2173.4375" y="879.6074">self.pid_error = vote.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="239" x="2173.4375" y="893.5762">self.measured_at = vote.measured_at</text><polygon fill="#FEFECE" filte
r="url(#f9dswc3p3ycf8)" points="1693.125,1324.0859,1705.125,1336.0859,1693.125,1348.0859,1681.125,1336.0859,1693.125,1324.0859" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="61.9063" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="314" x="2790.4375" y="573.8281"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="294" x="2800.4375" y="594.9668">n.new_bw = n.use_bw + n.use_bw * n.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="186" x="2800.4375" y="608.9355">n.pid_error_sum = n.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="132" x="2800.4375" y="622.9043">n.pid_bw = n.new_bw</text><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="2319,1354.0859,2331,1366.0859,2319,1378.0859,2307,1366.0859,2319,135
4.0859" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="289" x="2174.5" y="1494.8906"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="269" x="2184.5" y="1516.0293">prev_consensus[n.idhex].measured = True</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="176" x="2231" y="1563.8594"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="156" x="2241" y="1584.998">tot_net_bw += n.new_bw</text><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="2192.5,1446.4883,2445.5,1446.4883,2457.5,1458.4883,2445.5,1470.4883,2192.5,1470.4883,2180.5,1458.4883,2192.5,1446.4883" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-s
erif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="2323" y="1480.6987">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="253" x="2192.5" y="1462.2964">prev_consensus[n.idhex].bandwidth != None</text><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="2319,1617.8281,2331,1629.8281,2319,1641.8281,2307,1629.8281,2319,1617.8281" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="2243,1398.0859,2395,1398.0859,2407,1410.0859,2395,1422.0859,2243,1422.0859,2231,1410.0859,2243,1398.0859" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="2323" y="1432.2964">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="152" x="2243" y="1413.894">n.idhex in prev_consensus</text><polygon fil
l="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="2319,1661.8281,2331,1673.8281,2319,1685.8281,2307,1673.8281,2319,1661.8281" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="2242,192.8594,2396,192.8594,2408,204.8594,2396,216.8594,2242,216.8594,2230,204.8594,2242,192.8594" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="154" x="2242" y="208.6675">for n in nodes.itervalues()?</text><rect fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="55" x="2291.5" y="1771.8281"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="35" x="2301.5" y="1792.9668">cap...</text><polygon fill="#FEFECE" filter="url(#f9dswc3p3ycf8)" points="2242,1727.8281,2396,1727.8281,2408,1739.8281,2396,1751.8281,2242,1751.8281,2230
,1739.8281,2242,1727.8281" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="154" x="2242" y="1743.6362">for n in nodes.itervalues()?</text><ellipse cx="2220" cy="1781.8281" fill="none" filter="url(#f9dswc3p3ycf8)" rx="10" ry="10" style="stroke: #000000; stroke-width: 1.0;"/><ellipse cx="2220.5" cy="1782.3281" fill="#000000" filter="url(#f9dswc3p3ycf8)" rx="6" ry="6" style="stroke: none; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="64.9219" y2="84.9219"/><polygon fill="#A80036" points="2315,74.9219,2319,84.9219,2323,74.9219,2319,78.9219" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="118.8906" y2="138.8906"/><polygon fill="#A80036" points="2315,128.8906,2319,138.8906,2323,128.8906,2319,132.8906" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80
036; stroke-width: 1.5;" x1="2319" x2="2319" y1="270.8281" y2="290.8281"/><polygon fill="#A80036" points="2315,280.8281,2319,290.8281,2323,280.8281,2319,284.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="324.7969" y2="344.7969"/><polygon fill="#A80036" points="2315,334.7969,2319,344.7969,2323,334.7969,2319,338.7969" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="378.7656" y2="437.3125"/><polygon fill="#A80036" points="2315,427.3125,2319,437.3125,2323,427.3125,2319,431.3125" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="168" x2="168" y1="1043.9531" y2="1127.5"/><polygon fill="#A80036" points="164,1117.5,168,1127.5,172,1117.5,168,1121.5" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="786" x2="786" y1="1036.3867" y2="1112.3672"/><polyg
on fill="#A80036" points="782,1102.3672,786,1112.3672,790,1102.3672,786,1106.3672" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="396" x2="168" y1="939.4375" y2="939.4375"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="168" x2="168" y1="939.4375" y2="1009.9844"/><polygon fill="#A80036" points="164,999.9844,168,1009.9844,172,999.9844,168,1003.9844" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="558" x2="786" y1="939.4375" y2="939.4375"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="786" x2="786" y1="939.4375" y2="1002.418"/><polygon fill="#A80036" points="782,992.418,786,1002.418,790,992.418,786,996.418" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="168" x2="168" y1="1231.3125" y2="1276.0859"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="168" x2="465" y1="1276.0859" y2="1276.0859"/><polygon fill="#A80036"
points="455,1272.0859,465,1276.0859,455,1280.0859,459,1276.0859" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="786" x2="786" y1="1258.0859" y2="1276.0859"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="786" x2="489" y1="1276.0859" y2="1276.0859"/><polygon fill="#A80036" points="499,1272.0859,489,1276.0859,499,1280.0859,495,1276.0859" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="477" x2="477" y1="874.1563" y2="927.4375"/><polygon fill="#A80036" points="473,917.4375,477,927.4375,481,917.4375,477,921.4375" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1375" x2="1375" y1="940.0313" y2="1023.5781"/><polygon fill="#A80036" points="1371,1013.5781,1375,1023.5781,1379,1013.5781,1375,1017.5781" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1944" x2="1944" y1="891.4844" y2="9
26.4844"/><polygon fill="#A80036" points="1940,916.4844,1944,926.4844,1948,916.4844,1944,920.4844" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1590" x2="1375" y1="834.7109" y2="834.7109"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1375" x2="1375" y1="834.7109" y2="906.0625"/><polygon fill="#A80036" points="1371,896.0625,1375,906.0625,1379,896.0625,1375,900.0625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1729" x2="1944" y1="834.7109" y2="834.7109"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1944" x2="1944" y1="834.7109" y2="857.5156"/><polygon fill="#A80036" points="1940,847.5156,1944,857.5156,1948,847.5156,1944,851.5156" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1375" x2="1375" y1="1127.3906" y2="1145.3906"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1375" x2="1647.5" y1="1145.3906" y
2="1145.3906"/><polygon fill="#A80036" points="1637.5,1141.3906,1647.5,1145.3906,1637.5,1149.3906,1641.5,1145.3906" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1944" x2="1944" y1="1030.2969" y2="1145.3906"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1944" x2="1671.5" y1="1145.3906" y2="1145.3906"/><polygon fill="#A80036" points="1681.5,1141.3906,1671.5,1145.3906,1681.5,1149.3906,1677.5,1145.3906" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="998.75" x2="477" y1="792.6992" y2="792.6992"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="477" x2="477" y1="792.6992" y2="840.1875"/><polygon fill="#A80036" points="473,830.1875,477,840.1875,481,830.1875,477,834.1875" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1137.75" x2="1659.5" y1="792.6992" y2="792.6992"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1
659.5" x2="1659.5" y1="792.6992" y2="821.9063"/><polygon fill="#A80036" points="1655.5,811.9063,1659.5,821.9063,1663.5,811.9063,1659.5,815.9063" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="477" x2="477" y1="1288.0859" y2="1306.0859"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="477" x2="1056.25" y1="1306.0859" y2="1306.0859"/><polygon fill="#A80036" points="1046.25,1302.0859,1056.25,1306.0859,1046.25,1310.0859,1050.25,1306.0859" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1659.5" x2="1659.5" y1="1157.3906" y2="1306.0859"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1659.5" x2="1080.25" y1="1306.0859" y2="1306.0859"/><polygon fill="#A80036" points="1090.25,1302.0859,1080.25,1306.0859,1090.25,1310.0859,1086.25,1306.0859" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1068.25" x2="1068.25" y1="727.7773" y2="
773.4922"/><polygon fill="#A80036" points="1064.25,763.4922,1068.25,773.4922,1072.25,763.4922,1068.25,767.4922" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2315.4375" x2="2315.4375" y1="735.3438" y2="788.625"/><polygon fill="#A80036" points="2311.4375,778.625,2315.4375,788.625,2319.4375,778.625,2315.4375,782.625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1618.625" x2="1068.25" y1="661.0938" y2="661.0938"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1068.25" x2="1068.25" y1="661.0938" y2="693.8086"/><polygon fill="#A80036" points="1064.25,683.8086,1068.25,693.8086,1072.25,683.8086,1068.25,687.8086" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1767.625" x2="2315.4375" y1="661.0938" y2="661.0938"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2315.4375" x2="2315.4375" y1="661.0938" y2="701.375"/><polygon
fill="#A80036" points="2311.4375,691.375,2315.4375,701.375,2319.4375,691.375,2315.4375,695.375" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1068.25" x2="1068.25" y1="1318.0859" y2="1336.0859"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1068.25" x2="1681.125" y1="1336.0859" y2="1336.0859"/><polygon fill="#A80036" points="1671.125,1332.0859,1681.125,1336.0859,1671.125,1340.0859,1675.125,1336.0859" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2315.4375" x2="2315.4375" y1="906.4063" y2="1336.0859"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2315.4375" x2="1705.125" y1="1336.0859" y2="1336.0859"/><polygon fill="#A80036" points="1715.125,1332.0859,1705.125,1336.0859,1715.125,1340.0859,1711.125,1336.0859" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1693.125" x2="1693.125" y1="610.9453" y2="649.0938"/><polyg
on fill="#A80036" points="1689.125,639.0938,1693.125,649.0938,1697.125,639.0938,1693.125,643.0938" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2214" x2="1693.125" y1="551.8281" y2="551.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1693.125" x2="1693.125" y1="551.8281" y2="576.9766"/><polygon fill="#A80036" points="1689.125,566.9766,1693.125,576.9766,1697.125,566.9766,1693.125,570.9766" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2424" x2="2947.4375" y1="551.8281" y2="551.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2947.4375" x2="2947.4375" y1="551.8281" y2="573.8281"/><polygon fill="#A80036" points="2943.4375,563.8281,2947.4375,573.8281,2951.4375,563.8281,2947.4375,567.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1693.125" x2="1693.125" y1="1348.0859" y2="1366.0859"/><line style="stro
ke: #A80036; stroke-width: 1.5;" x1="1693.125" x2="2307" y1="1366.0859" y2="1366.0859"/><polygon fill="#A80036" points="2297,1362.0859,2307,1366.0859,2297,1370.0859,2301,1366.0859" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2947.4375" x2="2947.4375" y1="635.7344" y2="1366.0859"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2947.4375" x2="2331" y1="1366.0859" y2="1366.0859"/><polygon fill="#A80036" points="2341,1362.0859,2331,1366.0859,2341,1370.0859,2337,1366.0859" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="471.2813" y2="539.8281"/><polygon fill="#A80036" points="2315,529.8281,2319,539.8281,2323,529.8281,2319,533.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="1528.8594" y2="1563.8594"/><polygon fill="#A80036" points="2315,1553.8594,2319,1563.8594,2323,1553.8594,2319,1
557.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="1470.4883" y2="1494.8906"/><polygon fill="#A80036" points="2315,1484.8906,2319,1494.8906,2323,1484.8906,2319,1488.8906" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2457.5" x2="2473.5" y1="1458.4883" y2="1458.4883"/><polygon fill="#A80036" points="2469.5,1536.3594,2473.5,1546.3594,2477.5,1536.3594,2473.5,1540.3594" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2473.5" x2="2473.5" y1="1458.4883" y2="1629.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2473.5" x2="2331" y1="1629.8281" y2="1629.8281"/><polygon fill="#A80036" points="2341,1625.8281,2331,1629.8281,2341,1633.8281,2337,1629.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="1597.8281" y2="1617.8281"/><poly
gon fill="#A80036" points="2315,1607.8281,2319,1617.8281,2323,1607.8281,2319,1611.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="1422.0859" y2="1446.4883"/><polygon fill="#A80036" points="2315,1436.4883,2319,1446.4883,2323,1436.4883,2319,1440.4883" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2407" x2="2495.5" y1="1410.0859" y2="1410.0859"/><polygon fill="#A80036" points="2491.5,1536.3594,2495.5,1546.3594,2499.5,1536.3594,2495.5,1540.3594" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2495.5" x2="2495.5" y1="1410.0859" y2="1673.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2495.5" x2="2331" y1="1673.8281" y2="1673.8281"/><polygon fill="#A80036" points="2341,1669.8281,2331,1673.8281,2341,1677.8281,2337,1673.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036;
stroke-width: 1.5;" x1="2319" x2="2319" y1="1641.8281" y2="1661.8281"/><polygon fill="#A80036" points="2315,1651.8281,2319,1661.8281,2323,1651.8281,2319,1655.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="1378.0859" y2="1398.0859"/><polygon fill="#A80036" points="2315,1388.0859,2319,1398.0859,2323,1388.0859,2319,1392.0859" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="216.8594" y2="236.8594"/><polygon fill="#A80036" points="2315,226.8594,2319,236.8594,2323,226.8594,2319,230.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="1685.8281" y2="1695.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="3118.4375" y1="1695.8281" y2="1695.8281"/><polygon fill="#A80036" points="3114.4375,936.2461,3118.4375,926.2461,3122.4375,936.2461,3118.4375,932.2461"
style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="3118.4375" x2="3118.4375" y1="204.8594" y2="1695.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="3118.4375" x2="2408" y1="204.8594" y2="204.8594"/><polygon fill="#A80036" points="2418,200.8594,2408,204.8594,2418,208.8594,2414,204.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2230" x2="24" y1="204.8594" y2="204.8594"/><polygon fill="#A80036" points="20,922.2461,24,932.2461,28,922.2461,24,926.2461" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="24" x2="24" y1="204.8594" y2="1707.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="24" x2="2319" y1="1707.8281" y2="1707.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="1707.8281" y2="1727.8281"/><polygon fill="#A80036" points="2315,1717.8281,2319,1727.8281,2323,1717.8281,2319,172
1.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="172.8594" y2="192.8594"/><polygon fill="#A80036" points="2315,182.8594,2319,192.8594,2323,182.8594,2319,186.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="1751.8281" y2="1771.8281"/><polygon fill="#A80036" points="2315,1761.8281,2319,1771.8281,2323,1761.8281,2319,1765.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2319" y1="1805.7969" y2="1815.7969"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2319" x2="2420" y1="1815.7969" y2="1815.7969"/><polygon fill="#A80036" points="2416,1786.8125,2420,1776.8125,2424,1786.8125,2420,1782.8125" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2420" x2="2420" y1="1739.8281" y2="1815.7969"/><line style="stroke: #A80036; s
troke-width: 1.5;" x1="2420" x2="2408" y1="1739.8281" y2="1739.8281"/><polygon fill="#A80036" points="2418,1735.8281,2408,1739.8281,2418,1743.8281,2414,1739.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2230" x2="2220" y1="1739.8281" y2="1739.8281"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2220" x2="2220" y1="1739.8281" y2="1771.8281"/><polygon fill="#A80036" points="2216,1761.8281,2220,1771.8281,2224,1761.8281,2220,1765.8281" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#888888" font-family="sans-serif" font-size="10" lengthAdjust="spacingAndGlyphs" textLength="119" x="1511.7188" y="1837.0791">last updated 2021-01-08</text><!--
+@startuml
+title "Torflow measurements scaling."
+
+:prev_votes = VoteSet();
+note right
+initialize measurements from previous Bandwidth File
+end note
+:tot_net_bw = 0;
+:;
+note right
+ for every measurement
+end note
+while (for n in nodes.itervalues()?)
+ :n.fbw_ratio = n.filt_bw/true_filt_avg[n.node_class()];
+ :n.sbw_ratio = n.strm_bw/true_strm_avg[n.node_class()];
+ :n.use_bw = n.desc_bw;
+ :n.pid_error = ...;
+ note right
+ if n.sbw_ratio > n.fbw_ratio:
+ #assert cs_junk.use_best_ratio == True
+ n.pid_error = (n.strm_bw - true_strm_avg[n.node_class()])
+ / true_strm_avg[n.node_class()]
+ else:
+ n.pid_error = (n.filt_bw - true_filt_avg[n.node_class()])
+ / true_filt_avg[n.node_class()]
+ 0 <= n.pid_error <= 500.0
+ end note
+ if (n.idhex in prev_votes.vote_map?) then (yes)
+ :;
+ note right
+ if n.measured_at >
+ prev_votes.vote_map[n.idhex].measured_at;
+ end note
+ if (measurement newer?) then (yes)
+ :;
+ note right
+ if n.idhex in prev_consensus
+ and ("Guard" in prev_consensus[n.idhex].flags
+ and "Exit" not in prev_consensus[n.idhex].flags)
+ end note
+ if (in prev_consensus, \nis guard \nbut not exit?) then (yes)
+ :;
+ note right
+ if n.idhex not in prev_votes.vote_map
+ or n.measured_at - prev_votes.vote_map[n.idhex].measured_at
+ > cs_junk.guard_sample_rate:
+ # cs_jung.guard_sample_rate = 2*7*24*60*60 # 2wks
+ end note
+ if (diff bigger than 2 weeks) then (yes)
+ :;
+ note right
+ # full feedback
+ n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ cs_junk.K_p,
+ cs_junk.K_i,
+ cs_junk.K_d,
+ cs_junk.K_i_decay)
+ = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ 1.0, 0, 0, 0)
+ end note
+ :self.prev_error = prev_vote.pid_error
+ self.pid_bw = self.use_bw
+ + self.use_bw * self.pid_error
+ # + self.desc_bw * self.pid_error
+ self.pid_error_sum = 0 + self.pid_error
+ n.new_bw = self.pid_bw;
+ else (no)
+ :;
+ note right
+ \# Use new measurement but not feedback
+ n.copy_vote(prev_vote.vote_map[n.idhex]));
+ n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ cs_junk.K_p,
+ cs_junk.K_i,
+ cs_junk.K_d,
+ 0.0, False)
+ end note
+ :\# self.new_bw = vote.bw * 1000
+ self.pid_bw = vote.pid_bw
+ self.pid_error_sum = vote.pid_error_sum
+ self.pid_delta = vote.pid_delta
+
+ n.new_bw = self.use_bw + self.use_bw * self_pid_error
+
+ n.measured_at = prev_vote.measured_at
+ n.pid_error = prev_vote.pid_error;
+ endif
+ else (no)
+ if (in prev_consensus, \nis guard and exit) then (yes)
+ :;
+ note right
+ n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ cs_junk.K_p*weight,
+ cs_junk.K_i*weight,
+ cs_junk.K_d*weight,
+ cs_junk.K_i_decay)
+ n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ 1.0*1.0, 0, 0, 0)
+ \# so, same code as for when diff is bigger than 2 weeks
+ end note
+ :self.prev_error = prev_vote.pid_error
+ self.pid_bw = self.use_bw
+ + self.use_bw * self.pid_error
+ # + self.desc_bw * self.pid_error
+ self.pid_error_sum = 0 + self.pid_error
+ n.new_bw = self.pid_bw;
+ else (no)
+ :;
+ note right
+ \#again, same code
+ end note
+ :self.prev_error = prev_vote.pid_error
+ self.pid_bw = self.use_bw
+ + self.use_bw * self.pid_error
+ # + self.desc_bw * self.pid_error
+ self.pid_error_sum = 0 + self.pid_error
+ n.new_bw = self.pid_bw;
+ endif
+ endif
+ else (no)
+ :;
+ note right
+ \# Reset values. Don't vote/sample this measurement round.
+ \# is in the previous bwfile, but haven't check the consensus
+ n.revert_to_vote(prev_votes.vote_map[n.idhex])
+ \# which calls again self.copy_vote(vote)
+ end note
+ :self.new_bw = prev_vote.bw*1000
+ self.pid_bw = prev_vote.pid_bw
+ self.pid_error_sum = prev_vote.pid_error_sum
+ self.pid_delta = prev_vote.pid_delta
+
+ self.pid_error = vote.pid_error
+ self.measured_at = vote.measured_at;
+
+ endif
+ else (no)
+ :n.new_bw = n.use_bw + n.use_bw * n.pid_error
+ n.pid_error_sum = n.pid_error
+ n.pid_bw = n.new_bw;
+ endif
+
+ if (n.idhex in prev_consensus) then (yes)
+ if (prev_consensus[n.idhex].bandwidth != None) then (yes)
+ :prev_consensus[n.idhex].measured = True;
+ :tot_net_bw += n.new_bw;
+ endif
+ endif
+endwhile
+while (for n in nodes.itervalues()?)
+ :cap...;
+endwhile
+stop
+
+footer last updated 2021-01-08
+@enduml
+
+PlantUML version 1.2018.13(Mon Nov 26 17:11:51 GMT 2018)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 11.0.9.1+1-post-Debian-1deb10u2
+Operating System: Linux
+OS Version: 4.19.0-13-amd64
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg>
\ No newline at end of file
diff --git a/docs/source/images/activity_torflow_scaling_simplified.svg b/docs/source/images/activity_torflow_scaling_simplified.svg
new file mode 100644
index 0000000..42ab119
--- /dev/null
+++ b/docs/source/images/activity_torflow_scaling_simplified.svg
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="1879px" preserveAspectRatio="none" style="width:2238px;height:1879px;" version="1.1" viewBox="0 0 2238 1879" width="2238px" zoomAndPan="magnify"><defs><filter height="300%" id="f1g4fkgeqyp6on" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><text fill="#000000" font-family="sans-serif" font-size="18" lengthAdjust="spacingAndGlyphs" textLength="702" x="767" y="26.708">"Torflow measurements scaling with PID control (Per relay scaled bandwidth)."</text><path d="M1600.625,35.3711 L1600.625,43.9375 L
1580.625,47.9375 L1600.625,51.9375 L1600.625,60.5039 A0,0 0 0 0 1600.625,60.5039 L1961.625,60.5039 A0,0 0 0 0 1961.625,60.5039 L1961.625,45.3711 L1951.625,35.3711 L1600.625,35.3711 A0,0 0 0 0 1600.625,35.3711 " fill="#FBFB77" filter="url(#f1g4fkgeqyp6on)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M1951.625,35.3711 L1951.625,45.3711 L1961.625,45.3711 L1951.625,35.3711 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="340" x="1606.625" y="52.438">initialize measurements from previous Bandwidth File</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="165" x="1415.625" y="30.9531"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="145" x="1425.625" y="52.0918">prev_votes = VoteSet()</text><rect fill="#FEFECE" filte
r="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="114" x="1441.125" y="84.9219"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="94" x="1451.125" y="106.0605">tot_net_bw = 0</text><path d="M1530.125,143.3086 L1530.125,151.875 L1510.125,155.875 L1530.125,159.875 L1530.125,168.4414 A0,0 0 0 0 1530.125,168.4414 L1702.125,168.4414 A0,0 0 0 0 1702.125,168.4414 L1702.125,153.3086 L1692.125,143.3086 L1530.125,143.3086 A0,0 0 0 0 1530.125,143.3086 " fill="#FBFB77" filter="url(#f1g4fkgeqyp6on)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M1692.125,143.3086 L1692.125,153.3086 L1702.125,153.3086 L1692.125,143.3086 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="151" x="1536.125" y="160.3755">for every measurement</text><rect fill="#FEFECE" filter="u
rl(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="1486.125" y="138.8906"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="1500.125" y="160.0293"/><rect fill="#FFFFFF" filter="url(#f1g4fkgeqyp6on)" height="331.2656" style="stroke: #000000; stroke-width: 2.0;" width="799.5" x="1305.125" y="227.6611"/><path d="M1503.125,228.6611 L1503.125,236.958 L1493.125,246.958 L1305.125,246.958 " fill="none" style="stroke: #000000; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="188" x="1308.125" y="241.6563">Intialize ratios and pid_error</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="337" x="1329.625" y="263.958"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAn
dGlyphs" textLength="317" x="1339.625" y="285.0967">n.fbw_ratio = n.filt_bw/true_filt_avg[n.node_class()]</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="366" x="1315.125" y="317.9268"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="346" x="1325.125" y="339.0654">n.sbw_ratio = n.strm_bw/true_strm_avg[n.node_class()]</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="161" x="1417.625" y="371.8955"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="141" x="1427.625" y="393.0342">n.use_bw = n.desc_bw</text><path d="M1700.625,415.8643 L1700.625,477.3955 L1680.625,481.3955 L1700.625,485.3955 L1700.625,546.9268 A0,0 0 0 0 1700.625,546.9268 L2094.625,546.9268 A0,0 0 0 0 2094.625,546.9268 L20
94.625,425.8643 L2084.625,415.8643 L1700.625,415.8643 A0,0 0 0 0 1700.625,415.8643 " fill="#FBFB77" filter="url(#f1g4fkgeqyp6on)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M2084.625,415.8643 L2084.625,425.8643 L2094.625,425.8643 L2084.625,415.8643 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="175" x="1706.625" y="432.9312">if n.sbw_ratio > n.fbw_ratio:</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="12" x="1706.625" y="448.064">1.</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="247" x="1722.625" y="448.064">assert cs_junk.use_best_ratio == True</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="373" x="1706.625" y="463.1968">n.pid_error = (n.strm_bw - true_strm_avg[n
.node_class()])</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="204" x="1786.625" y="478.3296">/ true_strm_avg[n.node_class()]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="30" x="1706.625" y="493.4624">else:</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="343" x="1706.625" y="508.5952">n.pid_error = (n.filt_bw - true_filt_avg[n.node_class()])</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="189" x="1786.625" y="523.728">/ true_filt_avg[n.node_class()]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="173" x="1706.625" y="538.8608">0 <= n.pid_error <= 500.0</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80
036; stroke-width: 1.5;" width="365" x="1315.625" y="464.4111"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="345" x="1325.625" y="485.5498">n.pid_error = max(bwstrm_i / bwstrm, bwfilt_i / bwfilt) - 1</text><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="1405.125,578.9268,1591.125,578.9268,1603.125,590.9268,1591.125,602.9268,1405.125,602.9268,1393.125,590.9268,1405.125,578.9268" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="186" x="1405.125" y="594.7349">n.idhex in prev_votes.vote_map?</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="1373.125" y="588.3325">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="1603.125" y="588.3325">no</text><path d="M987.25,612.9268 L987.25,
629.0596 L967.25,633.0596 L987.25,637.0596 L987.25,653.1924 A0,0 0 0 0 987.25,653.1924 L1295.25,653.1924 A0,0 0 0 0 1295.25,653.1924 L1295.25,622.9268 L1285.25,612.9268 L987.25,612.9268 A0,0 0 0 0 987.25,612.9268 " fill="#FBFB77" filter="url(#f1g4fkgeqyp6on)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M1285.25,612.9268 L1285.25,622.9268 L1295.25,622.9268 L1285.25,612.9268 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="123" x="993.25" y="629.9937">if n.measured_at ></text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="287" x="993.25" y="645.1265">prev_votes.vote_map[n.idhex].measured_at;</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="943.25" y="616.0752"/><text fill="#000000" font-family="san
s-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="957.25" y="637.2139"/><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="892.75,688.1924,1017.75,688.1924,1029.75,700.1924,1017.75,712.1924,892.75,712.1924,880.75,700.1924,892.75,688.1924" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="125" x="892.75" y="704.0005">measurement newer?</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="860.75" y="697.5981">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="1029.75" y="697.5981">no</text><path d="M533.5,722.1924 L533.5,738.3252 L513.5,742.3252 L533.5,746.3252 L533.5,762.458 A0,0 0 0 0 533.5,762.458 L875.5,762.458 A0,0 0 0 0 875.5,762.458 L875.5,732.1924 L865.5,722.1924 L533.5,722.1924 A0,0 0 0 0 533.5,722.1924 " fill
="#FBFB77" filter="url(#f1g4fkgeqyp6on)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M865.5,722.1924 L865.5,732.1924 L875.5,732.1924 L865.5,722.1924 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="179" x="539.5" y="739.2593">if n.idhex in prev_consensus</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="305" x="555.5" y="754.3921">and ("Guard" in prev_consensus[n.idhex].flags=</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="489.5" y="725.3408"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="503.5" y="746.4795"/><path d="M533.5,847.4697 L533.5,878.7354 L513.5,882.7354 L533.5,886.7354 L533.5,918.001 A0,0 0 0 0 533.5,918.001 L980.5,918
.001 A0,0 0 0 0 980.5,918.001 L980.5,857.4697 L970.5,847.4697 L533.5,847.4697 A0,0 0 0 0 533.5,847.4697 " fill="#FBFB77" filter="url(#f1g4fkgeqyp6on)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M970.5,847.4697 L970.5,857.4697 L980.5,857.4697 L970.5,847.4697 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="239" x="539.5" y="864.5366">if n.idhex not in prev_votes.vote_map</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="410" x="555.5" y="879.6694">or n.measured_at - prev_votes.vote_map[n.idhex].measured_at</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="194" x="571.5" y="894.8022">> cs_junk.guard_sample_rate:</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="352" x="571.5"
y="909.9351"># cs_jung.guard_sample_rate = 2*7*24*60*60 # 2wks</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="489.5" y="865.751"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="503.5" y="886.8896"/><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="395.5,953.001,607.5,953.001,619.5,965.001,607.5,977.001,395.5,977.001,383.5,965.001,395.5,953.001" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="212" x="395.5" y="968.8091">not exit diff NOT bigger than 2 weeks</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="363.5" y="962.4067">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength=
"14" x="619.5" y="962.4067">no</text><path d="M249,987.001 L249,1040.9658 L229,1044.9658 L249,1048.9658 L249,1102.9307 A0,0 0 0 0 249,1102.9307 L636,1102.9307 A0,0 0 0 0 636,1102.9307 L636,997.001 L626,987.001 L249,987.001 A0,0 0 0 0 249,987.001 " fill="#FBFB77" filter="url(#f1g4fkgeqyp6on)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M626,987.001 L626,997.001 L636,997.001 L626,987.001 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="280" x="255" y="1004.0679">\# Use new measurement but not feedback</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="283" x="255" y="1019.2007">n.copy_vote(prev_vote.vote_map[n.idhex]));</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="366" x="255" y="1034.3335">n.new_bw = n.get_pid_bw(prev_votes.vote_map[n
.idhex],</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="78" x="303" y="1049.4663">cs_junk.K_p,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="73" x="303" y="1064.5991">cs_junk.K_i,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="78" x="303" y="1079.7319">cs_junk.K_d,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="66" x="303" y="1094.8647">0.0, False)</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="205" y="1027.9814"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="219" y="1049.1201"/><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="145.7188" rx="12.5" ry="12.
5" style="stroke: #A80036; stroke-width: 1.5;" width="358" x="38" y="1137.9307"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="204" x="48" y="1159.0693">\# self.new_bw = vote.bw * 1000</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="159" x="48" y="1173.0381">self.pid_bw = vote.pid_bw</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="251" x="48" y="1187.0068">self.pid_error_sum = vote.pid_error_sum</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="189" x="48" y="1200.9756">self.pid_delta = vote.pid_delta</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="52" y="1214.9443"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="338
" x="48" y="1228.9131">n.new_bw = self.use_bw + self.use_bw * self_pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="52" y="1242.8818"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="258" x="48" y="1256.8506">n.measured_at = prev_vote.measured_at</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="206" x="48" y="1270.8193">n.pid_error = prev_vote.pid_error</text><path d="M818,987.001 L818,1048.5322 L798,1052.5322 L818,1056.5322 L818,1118.0635 A0,0 0 0 0 818,1118.0635 L1205,1118.0635 A0,0 0 0 0 1205,1118.0635 L1205,997.001 L1195,987.001 L818,987.001 A0,0 0 0 0 818,987.001 " fill="#FBFB77" filter="url(#f1g4fkgeqyp6on)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M1195,987.001 L1195,997.001 L1205,997.001 L1195,987.001 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text
fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="12" x="824" y="1004.0679">1.</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="80" x="840" y="1004.0679">full feedback</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="366" x="824" y="1019.2007">n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="78" x="888" y="1034.3335">cs_junk.K_p,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="73" x="888" y="1049.4663">cs_junk.K_i,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="78" x="888" y="1064.5991">cs_junk.K_d,</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdj
ust="spacingAndGlyphs" textLength="119" x="888" y="1079.7319">cs_junk.K_i_decay)</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="301" x="840" y="1094.8647">= n.get_pid_bw(prev_votes.vote_map[n.idhex],</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="73" x="900" y="1109.9976">1.0, 0, 0, 0)</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="774" y="1035.5479"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="788" y="1056.6865"/><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="103.8125" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="260" x="656" y="1153.0635"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="228" x
="666" y="1174.2021">self.prev_error = prev_vote.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="158" x="666" y="1188.1709">self.pid_bw = self.use_bw</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="182" x="682" y="1202.1396">+ self.use_bw * self.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="203" x="682" y="1216.1084"># + self.desc_bw * self.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="240" x="666" y="1230.0771">self.pid_error_sum = 0 + self.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="146" x="666" y="1244.0459">n.new_bw = self.pid_bw</text><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="501.5,1289.6494,513.5,1301
.6494,501.5,1313.6494,489.5,1301.6494,501.5,1289.6494" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="444,797.458,559,797.458,571,810.2627,559,823.0674,444,823.0674,432,810.2627,444,797.458" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="505.5" y="833.2778">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="111" x="444" y="807.6685">in prev_consensus,</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="53" x="444" y="820.4731">is guard?</text><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="501.5,1333.6494,513.5,1345.6494,501.5,1357.6494,489.5,1345.6494,501.5,1333.6494" style="stroke: #A80036; stroke-width: 1.5;"/><path d="M1441,722.1924 L1441,753.458 L1421,757.458 L1441,761.458 L14
41,792.7236 A0,0 0 0 0 1441,792.7236 L1854,792.7236 A0,0 0 0 0 1854,792.7236 L1854,732.1924 L1844,722.1924 L1441,722.1924 A0,0 0 0 0 1441,722.1924 " fill="#FBFB77" filter="url(#f1g4fkgeqyp6on)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M1844,722.1924 L1844,732.1924 L1854,732.1924 L1844,722.1924 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="392" x="1447" y="739.2593">\# Reset values. Don't vote/sample this measurement round.</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="384" x="1447" y="754.3921">\# is in the previous bwfile, but haven't check the consensus</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="309" x="1447" y="769.5249">n.revert_to_vote(prev_votes.vote_map[n.idhex])</text><text fill="#000000" font-family="sans-serif"
font-size="13" lengthAdjust="spacingAndGlyphs" textLength="258" x="1447" y="784.6577">\# which calls again self.copy_vote(vote)</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="1397" y="740.4736"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="1411" y="761.6123"/><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="117.7813" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="304" x="1257" y="827.7236"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="211" x="1267" y="848.8623">self.new_bw = prev_vote.bw*1000</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="192" x="1267" y="862.8311">self.pid_bw = prev_vote.pid_bw</text><text fill="#000000" font-family="sans-serif" font-size="1
2" lengthAdjust="spacingAndGlyphs" textLength="284" x="1267" y="876.7998">self.pid_error_sum = prev_vote.pid_error_sum</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="222" x="1267" y="890.7686">self.pid_delta = prev_vote.pid_delta</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="1271" y="904.7373"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="187" x="1267" y="918.7061">self.pid_error = vote.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="239" x="1267" y="932.6748">self.measured_at = vote.measured_at</text><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="955.25,1363.6494,967.25,1375.6494,955.25,1387.6494,943.25,1375.6494,955.25,1363.6494" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="
url(#f1g4fkgeqyp6on)" height="61.9063" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="314" x="1884" y="612.9268"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="294" x="1894" y="634.0654">n.new_bw = n.use_bw + n.use_bw * n.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="186" x="1894" y="648.0342">n.pid_error_sum = n.pid_error</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="132" x="1894" y="662.0029">n.pid_bw = n.new_bw</text><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="1498.125,1393.6494,1510.125,1405.6494,1498.125,1417.6494,1486.125,1405.6494,1498.125,1393.6494" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="289" x="
1353.625" y="1534.4541"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="269" x="1363.625" y="1555.5928">prev_consensus[n.idhex].measured = True</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="176" x="1410.125" y="1603.4229"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="156" x="1420.125" y="1624.5615">tot_net_bw += n.new_bw</text><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="1371.625,1486.0518,1624.625,1486.0518,1636.625,1498.0518,1624.625,1510.0518,1371.625,1510.0518,1359.625,1498.0518,1371.625,1486.0518" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="1502.125" y="1520.2622">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" len
gthAdjust="spacingAndGlyphs" textLength="253" x="1371.625" y="1501.8599">prev_consensus[n.idhex].bandwidth != None</text><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="1498.125,1657.3916,1510.125,1669.3916,1498.125,1681.3916,1486.125,1669.3916,1498.125,1657.3916" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="1422.125,1437.6494,1574.125,1437.6494,1586.125,1449.6494,1574.125,1461.6494,1422.125,1461.6494,1410.125,1449.6494,1422.125,1437.6494" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="1502.125" y="1471.8599">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="152" x="1422.125" y="1453.4575">n.idhex in prev_consensus</text><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="1498.125,1701.3916,1510.125,1713.3916,1498.125,1725.391
6,1486.125,1713.3916,1498.125,1701.3916" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="1421.125,192.8594,1575.125,192.8594,1587.125,204.8594,1575.125,216.8594,1421.125,216.8594,1409.125,204.8594,1421.125,192.8594" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="154" x="1421.125" y="208.6675">for n in nodes.itervalues()?</text><rect fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="55" x="1470.625" y="1811.3916"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="35" x="1480.625" y="1832.5303">cap...</text><polygon fill="#FEFECE" filter="url(#f1g4fkgeqyp6on)" points="1421.125,1767.3916,1575.125,1767.3916,1587.125,1779.3916,1575.125,1791.3916,1421.125,1791.3916,1409.125,1779.3916,1421.125,1
767.3916" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="154" x="1421.125" y="1783.1997">for n in nodes.itervalues()?</text><ellipse cx="1399.125" cy="1821.3916" fill="none" filter="url(#f1g4fkgeqyp6on)" rx="10" ry="10" style="stroke: #000000; stroke-width: 1.0;"/><ellipse cx="1399.625" cy="1821.8916" fill="#000000" filter="url(#f1g4fkgeqyp6on)" rx="6" ry="6" style="stroke: none; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="64.9219" y2="84.9219"/><polygon fill="#A80036" points="1494.125,74.9219,1498.125,84.9219,1502.125,74.9219,1498.125,78.9219" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="118.8906" y2="138.8906"/><polygon fill="#A80036" points="1494.125,128.8906,1498.125,138.8906,1502.125,128.8906,1498.125,132.8906" style="stroke: #A80036; str
oke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="297.9268" y2="317.9268"/><polygon fill="#A80036" points="1494.125,307.9268,1498.125,317.9268,1502.125,307.9268,1498.125,311.9268" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="351.8955" y2="371.8955"/><polygon fill="#A80036" points="1494.125,361.8955,1498.125,371.8955,1502.125,361.8955,1498.125,365.8955" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="405.8643" y2="464.4111"/><polygon fill="#A80036" points="1494.125,454.4111,1498.125,464.4111,1502.125,454.4111,1498.125,458.4111" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="217" x2="217" y1="1061.9502" y2="1137.9307"/><polygon fill="#A80036" points="213,1127.9307,217,1137.9307,221,1127.9307,217,1131.9307" style="stroke: #A800
36; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="786" x2="786" y1="1069.5166" y2="1153.0635"/><polygon fill="#A80036" points="782,1143.0635,786,1153.0635,790,1143.0635,786,1147.0635" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="383.5" x2="217" y1="965.001" y2="965.001"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="217" x2="217" y1="965.001" y2="1027.9814"/><polygon fill="#A80036" points="213,1017.9814,217,1027.9814,221,1017.9814,217,1021.9814" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="619.5" x2="786" y1="965.001" y2="965.001"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="786" x2="786" y1="965.001" y2="1035.5479"/><polygon fill="#A80036" points="782,1025.5479,786,1035.5479,790,1025.5479,786,1029.5479" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="217" x2="217" y1="1283.6494"
y2="1301.6494"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="217" x2="489.5" y1="1301.6494" y2="1301.6494"/><polygon fill="#A80036" points="479.5,1297.6494,489.5,1301.6494,479.5,1305.6494,483.5,1301.6494" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="786" x2="786" y1="1256.876" y2="1301.6494"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="786" x2="513.5" y1="1301.6494" y2="1301.6494"/><polygon fill="#A80036" points="523.5,1297.6494,513.5,1301.6494,523.5,1305.6494,519.5,1301.6494" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="501.5" x2="501.5" y1="899.7197" y2="953.001"/><polygon fill="#A80036" points="497.5,943.001,501.5,953.001,505.5,943.001,501.5,947.001" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="501.5" x2="501.5" y1="823.0674" y2="865.751"/><polygon fill="#A80036" points="497.5,855.751,501.5,865.751,505
.5,855.751,501.5,859.751" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="571" x2="1225" y1="810.2627" y2="810.2627"/><polygon fill="#A80036" points="1221,1070.1572,1225,1080.1572,1229,1070.1572,1225,1074.1572" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1225" x2="1225" y1="810.2627" y2="1345.6494"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1225" x2="513.5" y1="1345.6494" y2="1345.6494"/><polygon fill="#A80036" points="523.5,1341.6494,513.5,1345.6494,523.5,1349.6494,519.5,1345.6494" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="501.5" x2="501.5" y1="1313.6494" y2="1333.6494"/><polygon fill="#A80036" points="497.5,1323.6494,501.5,1333.6494,505.5,1323.6494,501.5,1327.6494" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="501.5" x2="501.5" y1="759.3096" y2="797.458"/><
polygon fill="#A80036" points="497.5,787.458,501.5,797.458,505.5,787.458,501.5,791.458" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1409" x2="1409" y1="774.4424" y2="827.7236"/><polygon fill="#A80036" points="1405,817.7236,1409,827.7236,1413,817.7236,1409,821.7236" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="880.75" x2="501.5" y1="700.1924" y2="700.1924"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="501.5" x2="501.5" y1="700.1924" y2="725.3408"/><polygon fill="#A80036" points="497.5,715.3408,501.5,725.3408,505.5,715.3408,501.5,719.3408" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1029.75" x2="1409" y1="700.1924" y2="700.1924"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1409" x2="1409" y1="700.1924" y2="740.4736"/><polygon fill="#A80036" points="1405,730.4736,1409,740.4736,1413,730.4736,1409,734.4736"
style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="501.5" x2="501.5" y1="1357.6494" y2="1375.6494"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="501.5" x2="943.25" y1="1375.6494" y2="1375.6494"/><polygon fill="#A80036" points="933.25,1371.6494,943.25,1375.6494,933.25,1379.6494,937.25,1375.6494" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1409" x2="1409" y1="945.5049" y2="1375.6494"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1409" x2="967.25" y1="1375.6494" y2="1375.6494"/><polygon fill="#A80036" points="977.25,1371.6494,967.25,1375.6494,977.25,1379.6494,973.25,1375.6494" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="955.25" x2="955.25" y1="650.0439" y2="688.1924"/><polygon fill="#A80036" points="951.25,678.1924,955.25,688.1924,959.25,678.1924,955.25,682.1924" style="stroke: #A80036; stroke-width: 1.0;"/><line
style="stroke: #A80036; stroke-width: 1.5;" x1="1393.125" x2="955.25" y1="590.9268" y2="590.9268"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="955.25" x2="955.25" y1="590.9268" y2="616.0752"/><polygon fill="#A80036" points="951.25,606.0752,955.25,616.0752,959.25,606.0752,955.25,610.0752" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1603.125" x2="2041" y1="590.9268" y2="590.9268"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2041" x2="2041" y1="590.9268" y2="612.9268"/><polygon fill="#A80036" points="2037,602.9268,2041,612.9268,2045,602.9268,2041,606.9268" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="955.25" x2="955.25" y1="1387.6494" y2="1405.6494"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="955.25" x2="1486.125" y1="1405.6494" y2="1405.6494"/><polygon fill="#A80036" points="1476.125,1401.6494,1486.125,1405.6494,1476.125,1409.6494,1480.125,1405.6
494" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2041" x2="2041" y1="674.833" y2="1405.6494"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2041" x2="1510.125" y1="1405.6494" y2="1405.6494"/><polygon fill="#A80036" points="1520.125,1401.6494,1510.125,1405.6494,1520.125,1409.6494,1516.125,1405.6494" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="498.3799" y2="578.9268"/><polygon fill="#A80036" points="1494.125,568.9268,1498.125,578.9268,1502.125,568.9268,1498.125,572.9268" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="1568.4229" y2="1603.4229"/><polygon fill="#A80036" points="1494.125,1593.4229,1498.125,1603.4229,1502.125,1593.4229,1498.125,1597.4229" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1
498.125" y1="1510.0518" y2="1534.4541"/><polygon fill="#A80036" points="1494.125,1524.4541,1498.125,1534.4541,1502.125,1524.4541,1498.125,1528.4541" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1636.625" x2="1652.625" y1="1498.0518" y2="1498.0518"/><polygon fill="#A80036" points="1648.625,1575.9229,1652.625,1585.9229,1656.625,1575.9229,1652.625,1579.9229" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1652.625" x2="1652.625" y1="1498.0518" y2="1669.3916"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1652.625" x2="1510.125" y1="1669.3916" y2="1669.3916"/><polygon fill="#A80036" points="1520.125,1665.3916,1510.125,1669.3916,1520.125,1673.3916,1516.125,1669.3916" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="1637.3916" y2="1657.3916"/><polygon fill="#A80036" points="1494.125,1647.3916,1498.125
,1657.3916,1502.125,1647.3916,1498.125,1651.3916" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="1461.6494" y2="1486.0518"/><polygon fill="#A80036" points="1494.125,1476.0518,1498.125,1486.0518,1502.125,1476.0518,1498.125,1480.0518" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1586.125" x2="1674.625" y1="1449.6494" y2="1449.6494"/><polygon fill="#A80036" points="1670.625,1575.9229,1674.625,1585.9229,1678.625,1575.9229,1674.625,1579.9229" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1674.625" x2="1674.625" y1="1449.6494" y2="1713.3916"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1674.625" x2="1510.125" y1="1713.3916" y2="1713.3916"/><polygon fill="#A80036" points="1520.125,1709.3916,1510.125,1713.3916,1520.125,1717.3916,1516.125,1713.3916" style="stroke: #A80036; stroke-width: 1.0;"/><lin
e style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="1681.3916" y2="1701.3916"/><polygon fill="#A80036" points="1494.125,1691.3916,1498.125,1701.3916,1502.125,1691.3916,1498.125,1695.3916" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="1417.6494" y2="1437.6494"/><polygon fill="#A80036" points="1494.125,1427.6494,1498.125,1437.6494,1502.125,1427.6494,1498.125,1431.6494" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="216.8594" y2="263.958"/><polygon fill="#A80036" points="1494.125,253.958,1498.125,263.958,1502.125,253.958,1498.125,257.958" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="1725.3916" y2="1735.3916"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="2212" y1="1735.3916" y2="1735.3916"/><polygon
fill="#A80036" points="2208,949.6299,2212,939.6299,2216,949.6299,2212,945.6299" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2212" x2="2212" y1="204.8594" y2="1735.3916"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="2212" x2="1587.125" y1="204.8594" y2="204.8594"/><polygon fill="#A80036" points="1597.125,200.8594,1587.125,204.8594,1597.125,208.8594,1593.125,204.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1409.125" x2="24" y1="204.8594" y2="204.8594"/><polygon fill="#A80036" points="20,935.6299,24,945.6299,28,935.6299,24,939.6299" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="24" x2="24" y1="204.8594" y2="1747.3916"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="24" x2="1498.125" y1="1747.3916" y2="1747.3916"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="1747.3916"
y2="1767.3916"/><polygon fill="#A80036" points="1494.125,1757.3916,1498.125,1767.3916,1502.125,1757.3916,1498.125,1761.3916" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="172.8594" y2="192.8594"/><polygon fill="#A80036" points="1494.125,182.8594,1498.125,192.8594,1502.125,182.8594,1498.125,186.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="1791.3916" y2="1811.3916"/><polygon fill="#A80036" points="1494.125,1801.3916,1498.125,1811.3916,1502.125,1801.3916,1498.125,1805.3916" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1498.125" y1="1845.3604" y2="1855.3604"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1498.125" x2="1599.125" y1="1855.3604" y2="1855.3604"/><polygon fill="#A80036" points="1595.125,1826.376,1599.125,1816.376,1603.125,1826.376,159
9.125,1822.376" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1599.125" x2="1599.125" y1="1779.3916" y2="1855.3604"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1599.125" x2="1587.125" y1="1779.3916" y2="1779.3916"/><polygon fill="#A80036" points="1597.125,1775.3916,1587.125,1779.3916,1597.125,1783.3916,1593.125,1779.3916" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1409.125" x2="1399.125" y1="1779.3916" y2="1779.3916"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="1399.125" x2="1399.125" y1="1779.3916" y2="1811.3916"/><polygon fill="#A80036" points="1395.125,1801.3916,1399.125,1811.3916,1403.125,1801.3916,1399.125,1805.3916" style="stroke: #A80036; stroke-width: 1.0;"/><!--
+@startuml
+title "Torflow measurements scaling with PID control (Per relay scaled bandwidth)."
+
+:prev_votes = VoteSet();
+note right
+initialize measurements from previous Bandwidth File
+end note
+:tot_net_bw = 0;
+:;
+note right
+ for every measurement
+end note
+while (for n in nodes.itervalues()?)
+ partition "Intialize ratios and pid_error" {
+ :n.fbw_ratio = n.filt_bw/true_filt_avg[n.node_class()];
+ :n.sbw_ratio = n.strm_bw/true_strm_avg[n.node_class()];
+ :n.use_bw = n.desc_bw;
+ :n.pid_error = max(bwstrm_i / bwstrm, bwfilt_i / bwfilt) - 1;
+ note right
+ if n.sbw_ratio > n.fbw_ratio:
+ #assert cs_junk.use_best_ratio == True
+ n.pid_error = (n.strm_bw - true_strm_avg[n.node_class()])
+ / true_strm_avg[n.node_class()]
+ else:
+ n.pid_error = (n.filt_bw - true_filt_avg[n.node_class()])
+ / true_filt_avg[n.node_class()]
+ 0 <= n.pid_error <= 500.0
+ end note
+ }
+ if (n.idhex in prev_votes.vote_map?) then (yes)
+ :;
+ note right
+ if n.measured_at >
+ prev_votes.vote_map[n.idhex].measured_at;
+ end note
+ if (measurement newer?) then (yes)
+ :;
+ note right
+ if n.idhex in prev_consensus
+ and ("Guard" in prev_consensus[n.idhex].flags=
+ end note
+ if (in prev_consensus, \nis guard?) then (yes)
+ :;
+ note right
+ if n.idhex not in prev_votes.vote_map
+ or n.measured_at - prev_votes.vote_map[n.idhex].measured_at
+ > cs_junk.guard_sample_rate:
+ # cs_jung.guard_sample_rate = 2*7*24*60*60 # 2wks
+ end note
+ if (not exit diff NOT bigger than 2 weeks) then (yes)
+ :;
+ note right
+ \# Use new measurement but not feedback
+ n.copy_vote(prev_vote.vote_map[n.idhex]));
+ n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ cs_junk.K_p,
+ cs_junk.K_i,
+ cs_junk.K_d,
+ 0.0, False)
+ end note
+ :\# self.new_bw = vote.bw * 1000
+ self.pid_bw = vote.pid_bw
+ self.pid_error_sum = vote.pid_error_sum
+ self.pid_delta = vote.pid_delta
+
+ n.new_bw = self.use_bw + self.use_bw * self_pid_error
+
+ n.measured_at = prev_vote.measured_at
+ n.pid_error = prev_vote.pid_error;
+ else (no)
+ :;
+ note right
+ # full feedback
+ n.new_bw = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ cs_junk.K_p,
+ cs_junk.K_i,
+ cs_junk.K_d,
+ cs_junk.K_i_decay)
+ = n.get_pid_bw(prev_votes.vote_map[n.idhex],
+ 1.0, 0, 0, 0)
+ end note
+ :self.prev_error = prev_vote.pid_error
+ self.pid_bw = self.use_bw
+ + self.use_bw * self.pid_error
+ # + self.desc_bw * self.pid_error
+ self.pid_error_sum = 0 + self.pid_error
+ n.new_bw = self.pid_bw;
+ endif
+ endif
+ else (no)
+ :;
+ note right
+ \# Reset values. Don't vote/sample this measurement round.
+ \# is in the previous bwfile, but haven't check the consensus
+ n.revert_to_vote(prev_votes.vote_map[n.idhex])
+ \# which calls again self.copy_vote(vote)
+ end note
+ :self.new_bw = prev_vote.bw*1000
+ self.pid_bw = prev_vote.pid_bw
+ self.pid_error_sum = prev_vote.pid_error_sum
+ self.pid_delta = prev_vote.pid_delta
+
+ self.pid_error = vote.pid_error
+ self.measured_at = vote.measured_at;
+
+ endif
+ else (no)
+ :n.new_bw = n.use_bw + n.use_bw * n.pid_error
+ n.pid_error_sum = n.pid_error
+ n.pid_bw = n.new_bw;
+ endif
+
+ if (n.idhex in prev_consensus) then (yes)
+ if (prev_consensus[n.idhex].bandwidth != None) then (yes)
+ :prev_consensus[n.idhex].measured = True;
+ :tot_net_bw += n.new_bw;
+ endif
+ endif
+endwhile
+while (for n in nodes.itervalues()?)
+ :cap...;
+endwhile
+stop
+
+@enduml
+
+PlantUML version 1.2018.13(Mon Nov 26 17:11:51 GMT 2018)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 11.0.9.1+1-post-Debian-1deb10u2
+Operating System: Linux
+OS Version: 4.19.0-13-amd64
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg>
\ No newline at end of file
diff --git a/docs/source/images/activity_torflow_scaling_simplified1.svg b/docs/source/images/activity_torflow_scaling_simplified1.svg
new file mode 100644
index 0000000..c1de0ba
--- /dev/null
+++ b/docs/source/images/activity_torflow_scaling_simplified1.svg
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="976px" preserveAspectRatio="none" style="width:726px;height:976px;" version="1.1" viewBox="0 0 726 976" width="726px" zoomAndPan="magnify"><defs><filter height="300%" id="f1pyhrde7xrk7i" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><text fill="#000000" font-family="sans-serif" font-size="18" lengthAdjust="spacingAndGlyphs" textLength="702" x="12" y="26.708">"Torflow measurements scaling with PID control (Per relay scaled bandwidth)."</text><rect fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" he
ight="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="165" x="266.75" y="30.9531"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="145" x="276.75" y="52.0918">prev_votes = VoteSet()</text><rect fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="114" x="292.25" y="84.9219"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="94" x="302.25" y="106.0605">tot_net_bw = 0</text><path d="M381.25,143.3086 L381.25,151.875 L361.25,155.875 L381.25,159.875 L381.25,168.4414 A0,0 0 0 0 381.25,168.4414 L553.25,168.4414 A0,0 0 0 0 553.25,168.4414 L553.25,153.3086 L543.25,143.3086 L381.25,143.3086 A0,0 0 0 0 381.25,143.3086 " fill="#FBFB77" filter="url(#f1pyhrde7xrk7i)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M543.25,143.3086 L543.25,153.3086 L553.25,153.3086 L543.2
5,143.3086 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="151" x="387.25" y="160.3755">for every measurement</text><rect fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="24" x="337.25" y="138.8906"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="351.25" y="160.0293"/><rect fill="#FFFFFF" filter="url(#f1pyhrde7xrk7i)" height="244.1719" style="stroke: #000000; stroke-width: 2.0;" width="386" x="156.25" y="227.6611"/><path d="M354.25,228.6611 L354.25,236.958 L344.25,246.958 L156.25,246.958 " fill="none" style="stroke: #000000; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="188" x="159.25" y="241.6563">Intialize ratios and pid_error</text><rect f
ill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="337" x="180.75" y="263.958"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="317" x="190.75" y="285.0967">n.fbw_ratio = n.filt_bw/true_filt_avg[n.node_class()]</text><rect fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="366" x="166.25" y="317.9268"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="346" x="176.25" y="339.0654">n.sbw_ratio = n.strm_bw/true_strm_avg[n.node_class()]</text><rect fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="161" x="268.75" y="371.8955"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="141"
x="278.75" y="393.0342">n.use_bw = n.desc_bw</text><rect fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="308" x="195.25" y="425.8643"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="288" x="205.25" y="447.0029">n.pid_error = max(n.fbw_ratio, n.sbw_ratio) - 1</text><polygon fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" points="257.25,491.833,441.25,491.833,453.25,504.6377,441.25,517.4424,257.25,517.4424,245.25,504.6377,257.25,491.833" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="180" x="257.25" y="502.0435">n.idhex in prev_votes.vote_map</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="172" x="257.25" y="514.8481">and not newer measurement?</text><text fill="#000000" font-family="
sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="225.25" y="502.0435">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="453.25" y="502.0435">no</text><rect fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" height="47.9375" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="259" x="66.5" y="527.4424"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="211" x="76.5" y="548.5811">self.new_bw = prev_vote.bw*1000</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="239" x="76.5" y="562.5498">self.measured_at = vote.measured_at</text><rect fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="314" x="345.5" y="527.4424"/><text fill="#000000" font-family="sans-serif" font-size="12" length
Adjust="spacingAndGlyphs" textLength="294" x="355.5" y="548.5811">n.new_bw = n.use_bw + n.use_bw * n.pid_error</text><polygon fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" points="349.25,581.3799,361.25,593.3799,349.25,605.3799,337.25,593.3799,349.25,581.3799" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="289" x="204.75" y="675.3916"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="269" x="214.75" y="696.5303">prev_consensus[n.idhex].measured = True</text><rect fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="176" x="261.25" y="744.3604"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="156" x="271.25" y="765.499">tot_net_bw += n.new_bw</text><polygon fil
l="#FEFECE" filter="url(#f1pyhrde7xrk7i)" points="210.25,625.3799,488.25,625.3799,500.25,638.1846,488.25,650.9893,210.25,650.9893,198.25,638.1846,210.25,625.3799" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="353.25" y="661.1997">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="152" x="210.25" y="635.5903">n.idhex in prev_consensus</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="278" x="210.25" y="648.395">and prev_consensus[n.idhex].bandwidth != None</text><polygon fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" points="349.25,798.3291,361.25,810.3291,349.25,822.3291,337.25,810.3291,349.25,798.3291" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" points="272.25,192.8594,426.25,192.8594,438.25,204.85
94,426.25,216.8594,272.25,216.8594,260.25,204.8594,272.25,192.8594" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="154" x="272.25" y="208.6675">for n in nodes.itervalues()?</text><rect fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" height="33.9688" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="55" x="321.75" y="908.3291"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="35" x="331.75" y="929.4678">cap...</text><polygon fill="#FEFECE" filter="url(#f1pyhrde7xrk7i)" points="272.25,864.3291,426.25,864.3291,438.25,876.3291,426.25,888.3291,272.25,888.3291,260.25,876.3291,272.25,864.3291" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="154" x="272.25" y="880.1372">for n in nodes.itervalues()?</text><ellipse cx=
"250.25" cy="918.3291" fill="none" filter="url(#f1pyhrde7xrk7i)" rx="10" ry="10" style="stroke: #000000; stroke-width: 1.0;"/><ellipse cx="250.75" cy="918.8291" fill="#000000" filter="url(#f1pyhrde7xrk7i)" rx="6" ry="6" style="stroke: none; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="64.9219" y2="84.9219"/><polygon fill="#A80036" points="345.25,74.9219,349.25,84.9219,353.25,74.9219,349.25,78.9219" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="118.8906" y2="138.8906"/><polygon fill="#A80036" points="345.25,128.8906,349.25,138.8906,353.25,128.8906,349.25,132.8906" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="297.9268" y2="317.9268"/><polygon fill="#A80036" points="345.25,307.9268,349.25,317.9268,353.25,307.9268,349.25,311.9268" style="stroke: #A80036; stroke-width: 1.0;"/><line
style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="351.8955" y2="371.8955"/><polygon fill="#A80036" points="345.25,361.8955,349.25,371.8955,353.25,361.8955,349.25,365.8955" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="405.8643" y2="425.8643"/><polygon fill="#A80036" points="345.25,415.8643,349.25,425.8643,353.25,415.8643,349.25,419.8643" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="245.25" x2="196" y1="504.6377" y2="504.6377"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="196" x2="196" y1="504.6377" y2="527.4424"/><polygon fill="#A80036" points="192,517.4424,196,527.4424,200,517.4424,196,521.4424" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="453.25" x2="502.5" y1="504.6377" y2="504.6377"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="502.5" x2="502.5" y1="504.6377
" y2="527.4424"/><polygon fill="#A80036" points="498.5,517.4424,502.5,527.4424,506.5,517.4424,502.5,521.4424" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="196" x2="196" y1="575.3799" y2="593.3799"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="196" x2="337.25" y1="593.3799" y2="593.3799"/><polygon fill="#A80036" points="327.25,589.3799,337.25,593.3799,327.25,597.3799,331.25,593.3799" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="502.5" x2="502.5" y1="561.4111" y2="593.3799"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="502.5" x2="361.25" y1="593.3799" y2="593.3799"/><polygon fill="#A80036" points="371.25,589.3799,361.25,593.3799,371.25,597.3799,367.25,593.3799" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="459.833" y2="491.833"/><polygon fill="#A80036" points="345.25,481.833,349.25,491
.833,353.25,481.833,349.25,485.833" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="709.3604" y2="744.3604"/><polygon fill="#A80036" points="345.25,734.3604,349.25,744.3604,353.25,734.3604,349.25,738.3604" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="650.9893" y2="675.3916"/><polygon fill="#A80036" points="345.25,665.3916,349.25,675.3916,353.25,665.3916,349.25,669.3916" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="500.25" x2="512.25" y1="638.1846" y2="638.1846"/><polygon fill="#A80036" points="508.25,716.458,512.25,726.458,516.25,716.458,512.25,720.458" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="512.25" x2="512.25" y1="638.1846" y2="810.3291"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="512.25" x2="361.25" y1="810.
3291" y2="810.3291"/><polygon fill="#A80036" points="371.25,806.3291,361.25,810.3291,371.25,814.3291,367.25,810.3291" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="778.3291" y2="798.3291"/><polygon fill="#A80036" points="345.25,788.3291,349.25,798.3291,353.25,788.3291,349.25,792.3291" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="605.3799" y2="625.3799"/><polygon fill="#A80036" points="345.25,615.3799,349.25,625.3799,353.25,615.3799,349.25,619.3799" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="216.8594" y2="263.958"/><polygon fill="#A80036" points="345.25,253.958,349.25,263.958,353.25,253.958,349.25,257.958" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="822.3291" y2="832.3291"/><
line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="673.5" y1="832.3291" y2="832.3291"/><polygon fill="#A80036" points="669.5,498.6963,673.5,488.6963,677.5,498.6963,673.5,494.6963" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="673.5" x2="673.5" y1="204.8594" y2="832.3291"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="673.5" x2="438.25" y1="204.8594" y2="204.8594"/><polygon fill="#A80036" points="448.25,200.8594,438.25,204.8594,448.25,208.8594,444.25,204.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="260.25" x2="52.5" y1="204.8594" y2="204.8594"/><polygon fill="#A80036" points="48.5,484.6963,52.5,494.6963,56.5,484.6963,52.5,488.6963" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="52.5" x2="52.5" y1="204.8594" y2="844.3291"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="52.5" x2="349.25" y1="844
.3291" y2="844.3291"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="844.3291" y2="864.3291"/><polygon fill="#A80036" points="345.25,854.3291,349.25,864.3291,353.25,854.3291,349.25,858.3291" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="172.8594" y2="192.8594"/><polygon fill="#A80036" points="345.25,182.8594,349.25,192.8594,353.25,182.8594,349.25,186.8594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="888.3291" y2="908.3291"/><polygon fill="#A80036" points="345.25,898.3291,349.25,908.3291,353.25,898.3291,349.25,902.3291" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="349.25" y1="942.2979" y2="952.2979"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="349.25" x2="450.25" y1="952.2979" y2="952.2979"/><polygon fill="#A80036" points="44
6.25,923.3135,450.25,913.3135,454.25,923.3135,450.25,919.3135" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="450.25" x2="450.25" y1="876.3291" y2="952.2979"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="450.25" x2="438.25" y1="876.3291" y2="876.3291"/><polygon fill="#A80036" points="448.25,872.3291,438.25,876.3291,448.25,880.3291,444.25,876.3291" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="260.25" x2="250.25" y1="876.3291" y2="876.3291"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="250.25" x2="250.25" y1="876.3291" y2="908.3291"/><polygon fill="#A80036" points="246.25,898.3291,250.25,908.3291,254.25,898.3291,250.25,902.3291" style="stroke: #A80036; stroke-width: 1.0;"/><!--
+@startuml
+title "Torflow measurements scaling with PID control (Per relay scaled bandwidth)."
+
+:prev_votes = VoteSet();
+:tot_net_bw = 0;
+:;
+note right
+ for every measurement
+end note
+while (for n in nodes.itervalues()?)
+ partition "Intialize ratios and pid_error" {
+ :n.fbw_ratio = n.filt_bw/true_filt_avg[n.node_class()];
+ :n.sbw_ratio = n.strm_bw/true_strm_avg[n.node_class()];
+ :n.use_bw = n.desc_bw;
+ :n.pid_error = max(n.fbw_ratio, n.sbw_ratio) - 1;
+ }
+ if (n.idhex in prev_votes.vote_map \nand not newer measurement?) then (yes)
+ :self.new_bw = prev_vote.bw*1000
+ self.measured_at = vote.measured_at;
+ else (no)
+ :n.new_bw = n.use_bw + n.use_bw * n.pid_error;
+ endif
+
+ if (n.idhex in prev_consensus \nand prev_consensus[n.idhex].bandwidth != None) then (yes)
+ :prev_consensus[n.idhex].measured = True;
+ :tot_net_bw += n.new_bw;
+ endif
+endwhile
+while (for n in nodes.itervalues()?)
+ :cap...;
+endwhile
+stop
+
+@enduml
+
+PlantUML version 1.2018.13(Mon Nov 26 17:11:51 GMT 2018)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 11.0.9.1+1-post-Debian-1deb10u2
+Operating System: Linux
+OS Version: 4.19.0-13-amd64
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg>
\ No newline at end of file
diff --git a/docs/source/torflow_aggr.rst b/docs/source/torflow_aggr.rst
index e9ae3b6..ee832cd 100644
--- a/docs/source/torflow_aggr.rst
+++ b/docs/source/torflow_aggr.rst
@@ -1,7 +1,9 @@
.. _torflow_aggr:
-Torflow measurements aggregation
-==================================
+Torflow aggregation and scaling
+===============================
+
+.. seealso:: :ref:`generator` and :ref:`differences`.
Torflow aggregation or scaling goal is:
@@ -11,11 +13,180 @@ From Torflow's `README.spec.txt`_ (section 2.2)::
are effectively re-weighted proportional to how much faster the node
was as compared to the rest of the network.
-With and without PID control
+Initialization
+--------------
+
+Constants in consensus that Torflow uses and don't change::
+
+ bandwidth-weights Wbd=0 Wbe=0 [] Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 Wem=10000 Wgb=10000 Wgd=0 Wgg=5852 [] Wmb=10000 Wmd=0 Wme=0 [] Wmm=10000
+
+ params [] bwauthpid=1
+
+Constants in the code::
+
+ IGNORE_GUARD = 0
+ GUARD_SAMPLE_RATE = 2*7*24*60*60 # 2wks
+ MAX_AGE = 2*GUARD_SAMPLE_RATE; # 4 weeks
+
+ K_p = 1.0
+ T_i = 0
+ T_i_decay = 0
+ T_d = 0
+
+Initialization ``ConsensusJunk``::
+
+ self.bwauth_pid_control = True
+ self.group_by_class = False
+ self.use_pid_tgt = False
+ self.use_circ_fails = False
+ self.use_best_ratio = True
+ self.use_desc_bw = True
+ self.use_mercy = False
+ self.guard_sample_rate = GUARD_SAMPLE_RATE
+ self.pid_max = 500.0
+ self.K_p = K_p = 1.0
+ self.T_i = T_i = 0
+ self.T_d = T_d = 0
+ self.T_i_decay = T_i_decay = 0
+
+ self.K_i = 0
+ self.K_d = self.K_p*self.T_d = 0
+
+Initialization ``Node``::
+
+ self.sbw_ratio = None
+ self.fbw_ratio = None
+ self.pid_bw = 0
+ self.pid_error = 0
+ self.prev_error = 0
+ self.pid_error_sum = 0
+ self.pid_delta = 0
+ self.ratio = None
+ self.new_bw = None
+ self.use_bw = -1
+ self.flags = ""
+
+ # measurement vars from bwauth lines
+ self.measured_at = 0
+ self.strm_bw = 0
+ self.filt_bw = 0
+ self.ns_bw = 0
+ self.desc_bw = 0
+ self.circ_fail_rate = 0
+ self.strm_fail_rate = 0
+ self.updated_at = 0
+
+.. image:: ./images/activity_torflow_aggr.svg
+
+
+.. _relay-descriptors-bandwidth:
+
+Descriptor values for each relay
+--------------------------------
+
+From `TorCtl.py`_ code, it is the minimum of all the descriptor bandwidth
+values::
+
+ bws = map(int, g)
+ bw_observed = min(bws)
+
+ [snip]
+
+ return Router(ns.idhex, ns.nickname, bw_observed, dead, exitpolicy,
+ ns.flags, ip, version, os, uptime, published, contact, rate_limited,
+ ns.orhash, ns.bandwidth, extra_info_digest, ns.unmeasured)
+
+``ns.bandwidth`` is the consensus bandwidth, already multiplied by 1000::
+
+ yield NetworkStatus(*(m.groups()+(flags,)+(int(w.group(1))*1000,))+(unmeasured,))
+
+Because of the matched regular expression, ``bws`` is **not** all the descriptor
+bandwidth values, but the average bandwidth and the observed bandwidth, ie., it
+does not take the average burst, what seems to be a bug in Torflow.
+
+Eg. ``bandwidth`` line in a descriptor::
+
+ bandwidth 1536000 4096000 1728471
+
+Only takes the first and last values, so::
+
+ bw_observed = min(bandwidth-avg, bandwidth-observed)
+
+This is passed to ``Router``, in which the descriptors bandwidth is assigned to
+the consensus bandwidth when there is no consensus bandwidth::
+
+ (idhex, name, bw, down, exitpolicy, flags, ip, version, os, uptime,
+ published, contact, rate_limited, orhash,
+ ns_bandwidth,extra_info_digest,unmeasured) = args
+
+ [snip]
+
+ if ns_bandwidth != None:
+ self.bw = max(ns_bandwidth,1) # Avoid div by 0
+ else:
+ self.bw = max(bw,1) # Avoid div by 0
+
+ [snip]
+
+ self.desc_bw = max(bw,1) # Avoid div by 0
+
+So::
+
+ self.bw = ns_bwandwidth or min(bandwidth-avg, bandwidth-observed) or 1
+ desc_bw = min(bandwidth-avg, bandwidth-observed) or 1
+
+And written by `SQLSupport.py`_ as descriptor and conensus bandwidth::
+
+ f.write(" desc_bw="+str(int(cvt(s.avg_desc_bw,0))))
+ f.write(" ns_bw="+str(int(cvt(s.avg_bw,0)))+"\n")
+
+.. _relay-descriptor-bandwidth-pid:
+
+Descriptor bandwidth with PID control
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Even though `README.spec.txt`_ talks about the consensus bandwidth, in
+`aggregate.py`_ code, the consensus bandwidth is never used, since
+``use_desc_bw`` is initialized to True and never changed::
+
+ if cs_junk.bwauth_pid_control:
+ if cs_junk.use_desc_bw:
+ n.use_bw = n.desc_bw
+ else:
+ n.use_bw = n.ns_bw
+
+So::
+
+ n.use_bw = n.desc_bw = min(bandwidth-avg, bandwidth-observed) or 1
+
+
+Scaling the raw measurements
----------------------------
-Per relay measurements' bandwidth
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. _overview:
+
+Overview
+~~~~~~~~
+
+This diagram also includes
+:ref:`relay-descriptor-bandwidth-pid`,
+:ref:`relay-bandwidth-ratio` and :ref:`relay-scaled-bandwidth-pid`.
+
+.. image:: ./images/activity_torflow_scaling_simplified1.svg
+
+Simplified image from:
+
+.. image:: ./images/activity_torflow_scaling_simplified.svg
+
+`<./_images/activity_torflow_scaling_simplified.svg>`_
+
+.. image:: ./images/activity_torflow_scaling.svg
+
+`<./_images/activity_torflow_scaling.svg>`_
+
+
+Stream and filtered bandwidth for each relay
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
They are calculated in the same way whether or not `PID controller`_ feedback
is used.
@@ -56,21 +227,16 @@ In the code, `SQLSupport.py`_, ``strm_bw`` is ``sbw`` and
This is also expressed in pseudocode in the `bandwidth file spec`_, section B.4
step 1.
-Calling ``bw_i`` to ``strm_bw`` and ``bwfilt_i`` to ``filt_bw``,
-if ``bw_j`` is a measurement for a relay ``i`` and ``m`` is the number of
-measurements for that relay, then:
-
-.. math::
+Calling ``bwstrm_i`` to ``strm_bw`` and ``bwfilt_i`` to ``filt_bw``,
+if ``bw_j`` is a measurement for a relay ``i``, then:::
- bw_i = \mu(bw_j) = \frac{\sum_{j=1}^{m}bw_j}{m}
+ bwstrm_i = mean(bw_j) # for a relay, the average of all its measurements
+ bwfilt_i = mean(max(bwstrm_i, bw_j))
-.. math::
+.. _stream-and-filtered-bandwidth-for-all-relays:
- bwfilt_i &= \mu(max(\mu(bw_j), bw_j))
- = \frac{\sum_{j=1}^{m} max\left(\frac{\sum_{j=1}^{m}bw_j}{m}, bw_j\right)}{m}
-
-Network measurements' bandwidth average
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Stream and filtered bandwidth for all relays
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
From `README.spec.txt`_ (section 2.1)::
@@ -79,34 +245,35 @@ From `README.spec.txt`_ (section 2.1)::
In Torflow's `aggregate.py`_ code::
- filt_avg = sum(map(lambda n: n.filt_bw, nodes.itervalues()))/float(len(nodes))
- strm_avg = sum(map(lambda n: n.strm_bw, nodes.itervalues()))/float(len(nodes))
-
-Both in the code with PID and without, all types of nodes get the same
-average.
+ for cl in ["Guard+Exit", "Guard", "Exit", "Middle"]:
+ c_nodes = filter(lambda n: n.node_class() == cl, nodes.itervalues())
+ if len(c_nodes) > 0:
+ true_filt_avg[cl] = sum(map(lambda n: n.filt_bw, c_nodes))/float(len(c_nodes))
+ true_strm_avg[cl] = sum(map(lambda n: n.strm_bw, c_nodes))/float(len(c_nodes))
+ true_circ_avg[cl] = sum(map(lambda n: (1.0-n.circ_fail_rate),
+ c_nodes))/float(len(c_nodes))
-This is also expressed in pseudocode in the `bandwidth file spec`_, section B.4
-step 2.
+The following code seems to be used only to log::
-Calling ``bwstrm`` to ``strm_avg`` and ``bwfilt`` to ``fitl_avg``, if ``n`` is
-the number of relays in the network, then:
+ filt_avg = sum(map(lambda n: n.filt_bw, nodes.itervalues()))/float(len(nodes))
+ strm_avg = sum(map(lambda n: n.strm_bw, nodes.itervalues()))/float(len(nodes))
-.. math::
+So it seems the ``filt_avg`` and ``strm_avg`` are calculated by class in both
+the cases with PID control and without PID control.
- bwstrm &= \mu(bw_i)
- = \frac{\sum_{i=1}^{n}bw_i}{n}
- = \frac{\sum_{i=1}^{n} \frac{\sum_{j=1}^{m}bw_j}{m} }{n}
+Calling ``bwstrm`` to ``strm_avg`` and ``bwfilt`` to ``fitl_avg``, without
+taking into account the different types of nodes::
-.. math::
+ bwstrm = mean(bwstrm_i)
+ bwfilt = mean(bwfilt_i)
- bwfilt &= \mu(bwfilt_i)
- = \frac{\sum_{i=1}^{n}bwfilt_i}{n}
- = \frac{\sum_{i=1}^{n}\frac{\sum_{j=1}^{m}max(\mu(bw_j), bw_j)}{m}}{n}
- = \frac{\sum_{i=1}^{n}\frac{\sum_{j=1}^{m}max\left(\frac{\sum_{j=1}^{m}bw_j}{m}, bw_j\right)}{m}}{n}
+This is also expressed in pseudocode in the `bandwidth file spec`_, section B.4
+step 2.
+.. _relay-bandwidth-ratio:
-Per relay bandwidth ratio
-~~~~~~~~~~~~~~~~~~~~~~~~~
+Ratio for each relay
+~~~~~~~~~~~~~~~~~~~~
From `README.spec.txt`_ (section 2.2)::
@@ -127,72 +294,17 @@ In Torflow's `aggregate.py`_ code::
else:
n.ratio = n.fbw_ratio
-This is also expressed in pseudocode in the `bandwidth file spec`_, section B.4
-step 2 and 3.
-
-Calling ``rf_i`` to ``fbw_ratio`` and ``rs_i`` to ``sbw_ration`` and ``r_i``
-to ``ratio``:
-
-.. math::
-
- rf_i = \frac{bwfilt_i}{bwfilt}
-
- rs_i = \frac{bw_i}{bwstrm}
-
-
-.. math::
-
- r_i = max(rf_i, rs_i)
- = max\left(\frac{bwfilt_i}{bwfilt}, \frac{bw_i}{bwstrm}\right)
- = max\left(\frac{bwfilt_i}{\mu(bwfilt_i)}, \frac{bw_i}{\mu(bwfilt_i)}\right)
-
-Per relay descriptors bandwidth
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-From `TorCtl.py`_ code, it is the minimum of all the descriptor bandwidth
-values::
-
- bws = map(int, g)
- bw_observed = min(bws)
-
- [snip]
-
- return Router(ns.idhex, ns.nickname, bw_observed, dead, exitpolicy,
- ns.flags, ip, version, os, uptime, published, contact, rate_limited,
- ns.orhash, ns.bandwidth, extra_info_digest, ns.unmeasured)
-
-Because of the matched regular expression, ``bws`` is **not** all the descriptor
-bandwidth values, but the observed bandwidth and the burst bandwidth, ie., it
-does not take the average bandwidth, what seems to be a bug in Torflow.
-
-This is passed to ``Router``, in which the consensus bandwidth is assigned to the
-descriptor bandwidth when there is no consensus bandwidth::
-
- (idhex, name, bw, down, exitpolicy, flags, ip, version, os, uptime,
- published, contact, rate_limited, orhash,
- ns_bandwidth,extra_info_digest,unmeasured) = args
-
- [snip]
-
- if ns_bandwidth != None:
- self.bw = max(ns_bandwidth,1) # Avoid div by 0
- else:
- self.bw = max(bw,1) # Avoid div by 0
-
- [snip]
-
- self.desc_bw = max(bw,1) # Avoid div by 0
+So::
-And written by `SQLSupport.py`_ as descriptor and conensus bandwidth::
+ n.ratio = max(sbw_ratio, n.fbw_ratio)
- f.write(" desc_bw="+str(int(cvt(s.avg_desc_bw,0))))
- f.write(" ns_bw="+str(int(cvt(s.avg_bw,0)))+"\n")
+This is also expressed in pseudocode in the `bandwidth file spec`_, section B.4
+step 2 and 3.
-Without PID control
--------------------
+.. relay-scaled-no-pid:
-Per relay scaled bandwidth
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+Scaled bandwidth for each relay without PID control
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
From `README.spec.txt`_ (section 2.2)::
@@ -204,46 +316,20 @@ In `aggregate.py`_ code::
n.new_bw = n.desc_bw*n.ratio
-This is also expressed in pseudocode in the `bandwidth file spec`_, section B.4
-step 5.
-
-Calling ``bwnew_i`` to ``new_bw`` and ``descbw_i`` to ``use_bw``:
-
-.. math::
-
- descbw_i = min\left(bwobs_i, bwavg_i, bwburst_i, measuredconsensusbw_i \right)
-
- bwnew_i =& descbw_i \times r_i \
-
- &= min\left(bwobs_i, bwavg_i, bwburst_i, measuredconsensusbw_i \right) \times max(rf_i, rs_i) \
-
- &= min\left(bwobs_i, bwavg_i, bwburst_i, measuredconsensusbw_i \right) \times max\left(\frac{bwfilt_i}{bwfilt}, \frac{bw_i}{bwstrm}\right) \
-
- &= min\left(bwobs_i, bwavg_i, bwburst_i, measuredconsensusbw_i \right) \times max\left(\frac{bwfilt_i}{\mu(bwfilt_i)}, \frac{bw_i}{\mu(bw_i)}\right)
-
-
-With PID control
-----------------
-
-Per relay descriptors bandwidth
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Even though `README.spec.txt`_ talks about the consensus bandwidth, in
-`aggregate.py`_ code, the consensus bandwidth is never used, since
-``use_desc_bw`` is initialized to True and never changed::
+So::
- self.use_desc_bw = True
+ n.new_bw = (
+ min(bandwidth-avg, bandwidth-observed) or 1 \
+ * max(bwstrm_i / bwstrm, bwfilt_i / bwfilt_i)
+ )
- [snip]
+This is also expressed in pseudocode in the `bandwidth file spec`_, section B.4
+step 5.
- if cs_junk.bwauth_pid_control:
- if cs_junk.use_desc_bw:
- n.use_bw = n.desc_bw
- else:
- n.use_bw = n.ns_bw
+.. _relay-scaled-bandwidth-pid:
-Per relay scaled bandwidth
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+Scaled bandwidth for each relay with PID control
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
From `README.spec.txt`_ section 3.1::
@@ -292,38 +378,58 @@ greater::
n.new_bw = n.use_bw + cs_junk.K_p*n.use_bw*n.pid_error
-Calling ``e_i`` to ``pid_error``, in the case that ``rs_i`` > ``rf_i``:
+So::
-.. math::
+ if (bwstrm_i / bwstrm) > (bwfilt_i / bwfilt):
+ pid_error = (bwstrm_i - bwstrm) / bwstrm = (bwstrm_i / bwstrm) - 1
+ else:
+ pid_error = (bwfilt_i - bwfilt_i) / bwfilt = (bwfilt_i / bwfilt) - 1
- e_i = \frac{bw_i - bwstrm}{bwstrm} = \frac{bw_i}{bwstrm} - 1
+ new_bw = use_bw + use_bw * pid_error
- bwn_i = descbw_i + descbw_i \times e_i = descbw_i \times (1 + e_i)
- = descbw_i \times (1 + \frac{bw_i}{bwstrm} - 1)
- = descbw_i \times \frac{bw_i}{bwstrm} = descbw_i \times rs_i
+Or::
-And in the case that ``rs_i`` < ``rf_i``:
+ if (bwstrm_i / bwstrm) > (bwfilt_i / bwfilt):
+ new_bw = use_bw + use_bw * ((bwstrm_i / bwstrm) - 1)
+ new_bw = use_bw + use_bw * (bwstrm_i / bwstrm) - use_bw
+ new_bw = use_bw * (bwstrm_i / bwstrm)
+ else:
+ new_bw = use_bw + use_bw * ((bwfilt_i / bwfilt) - 1)
+ new_bw = use_bw + use_bw * (bwfilt_i / bwfilt) - use_bw
+ new_bw = use_bw * (bwfilt_i / bwfilt)
-.. math::
+Or::
- e_i = \frac{bwfilt_i - bwfilt}{bwfilt} = \frac{bwfilt_i}{bwfilt} - 1
+ new_bw = use_bw * max(bwstrm_i / bwstrm, bwfilt_i / bwfilt)
+ new_bw = (
+ min(bandwidth-avg, bandwidth-observed) or 1
+ * max(bwstrm_i / bwstrm, bwfilt_i / bwfilt)
+ )
- bwn_i = descbw_i + descbw_i \times e_i = descbw_i \times (1 + e_i)
- = descbw_i \times (1 + \frac{bwfilt_i}{bwfilt} - 1)
- = descbw_i \times \frac{bwfilt_i}{bwfilt} = descbw_i \times rf_i
+.. note::
+ So, the new scaled bandwidth is the same for both cases with and without
+ PID controller!
-So, it is the same as the scaled bandwidth in the case without PID controller,
-ie.:
+Other pid KeyValues in the Bandwidth File
+-----------------------------------------
-.. math::
+.. note::
- bwn_i = descbw_i \times max(rf_i, rs_i)
+ From the :ref:`overview` it seems that the only variable needed to
+ calculate the new scaled bandwidth is the ``pid_error``, and from
+ :ref:`relay-descriptor-bandwidth-pid`, it can be substituted
+ by the stream and filtered bandwidths.
-With and without PID control
-----------------------------
+This are the variables that can then be ignored::
+
+ pid_error_sum
+ pid_delta
+ prev_error
+
+Limit scaled bandwidth for each relay
+-------------------------------------
-Per relay scaled bandwidth limit
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+It's calculated the same with and without PID control
Once each relay bandwidth is scaled, it is limited to a maximum, that is
calculated as the sum of all the relays in the current consensus scaled
@@ -347,40 +453,8 @@ From `aggregate.py`_ code::
n.new_bw = int(tot_net_bw*NODE_CAP)
-.. math::
-
- bwn_i =& min\left(bwnew_i,
- \sum_{i=1}^{n}bwnew_i \times 0.05\right) \
-
- &= min\left(
- \left(min\left(bwobs_i, bwavg_i, bwburst_i, measuredconsensusbw_i \right) \times r_i\right),
- \sum_{i=1}^{n}\left(min\left(bwobs_i, bwavg_i, bwburst_i, measuredconsensusbw_i \right) \times r_i\right)
- \times 0.05\right)\
-
- &= min\left(
- \left(min\left(bwobs_i, bwavg_i, bwburst_i, measuredconsensusbw_i \right) \times max\left(rf_i, rs_i\right)\right),
- \sum_{i=1}^{n}\left(min\left(bwobs_i, bwavg_i, bwburst_i, measuredconsensusbw_i \right) \times
- max\left(rf_i, rs_i\right)\right) \times 0.05\right)\
-
- &= min\left(
- \left(min\left(bwobs_i, bwavg_i, bwburst_i, measuredconsensusbw_i \right) \times max\left(\frac{bwfilt_i}{bwfilt},
- \frac{bw_i}{bwstrm}\right)\right),
- \sum_{i=1}^{n}\left(min\left(bwobs_i, bwavg_i, bwburst_i, measuredconsensusbw_i \right) \times
- max\left(\frac{bwfilt_i}{bwfilt},
- \frac{bw_i}{bwstrm}\right)\right) \times 0.05\right)
-
-.. math::
-
- bwn_i = min\left(
- \left(min\left(bwobs_i, bwavg_i, bwburst_i, measuredconsensusbw_i \right) \times max\left(\frac{bwfilt_i}{bwfilt},
- \frac{bw_i}{bwstrm}\right)\right),
- \sum_{i=1}^{n}\left(min\left(bwobs_i, bwavg_i, bwburst_i, measuredconsensusbw_i \right) \times
- max\left(\frac{bwfilt_i}{bwfilt},
- \frac{bw_i}{bwstrm}\right)\right) \times 0.05\right)
-
-
-Per relay scaled bandwidth rounding
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Round the scaled bandwidth for each relay
+-----------------------------------------
Finally, the new scaled bandwidth is expressed in kilobytes and rounded a number
of digits.
1
0

26 Feb '21
commit f9e4549b7fa80c8d3f459b9dbc960673fca18270
Author: juga0 <juga(a)riseup.net>
Date: Thu Feb 18 12:34:23 2021 +0000
fix: doc: Update differences Torflow/sbws
Closes #40056
---
docs/source/differences.rst | 59 ++++++++++++++++++++++++++++-----------------
1 file changed, 37 insertions(+), 22 deletions(-)
diff --git a/docs/source/differences.rst b/docs/source/differences.rst
index 6f904e5..cf5e636 100644
--- a/docs/source/differences.rst
+++ b/docs/source/differences.rst
@@ -1,36 +1,51 @@
.. _differences:
-Differences between Torflow aggregation and sbws scaling (May 2020)
--------------------------------------------------------------------
+Differences between Torflow and sbws
+====================================
+
+(Last updated 2020-02-18)
+
+Aggregating measurements and scaling
+------------------------------------
+
+Filtering
+~~~~~~~~~
Torflow does not exclude relays because of having "few" measurements or "close"
-to each other for that relay.
+to each other for that relay, like sbws does :ref:`filtering-measurements`.
+
+However this is currently disabled in sbws.
+
+Network stream and filtered bandwidth
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Torflow calculates the network stream and filtered averages by type of relay
+:ref:`stream-and-filtered-bandwidth-for-all-relays`, while sbws is not taking
+into account the type of relay :ref:`scaling-the-bandwidth-measurements`.
-If there are not new measurements for a relay, Torflow uses the previous
-calculated bandwidth, instead of the new value::
+Values from the previous Bandwidth File
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # If there is a new sample, let's use it for all but guards
- if n.measured_at > prev_votes.vote_map[n.idhex].measured_at:
+sbws is not reading the previous Bandwidth File, but scaling all the values
+with the raw measurements.
- [snip]
+Instead, Torflow uses the previous Bandwidth File values in some cases:
- else:
- # Reset values. Don't vote/sample this measurement round.
- n.revert_to_vote(prev_votes.vote_map[n.idhex])
+- When a relay measurement is older than the one in the previous
+ Bandwidth File, it uses all the values from the previous Bandwidth File.
+ (how is possible that the Bandwidth File would have a newer measurements?)::
-The oldest measurements Toflow seems to take are from 4 weeks ago, while sbws
-oldest measurements are 5 days old::
+ self.new_bw = prev_vote.bw * 1000
- GUARD_SAMPLE_RATE = 2*7*24*60*60 # 2wks
+Bandwidth File KeyValues
+~~~~~~~~~~~~~~~~~~~~~~~~
- [snip]
+sbws does not calculate nor write to the Bandwidth file the ``pid`` variables
+and KeyValues that are used in Torflow. Example of Torflow KeyValues not in sbws::
- MAX_AGE = 2*GUARD_SAMPLE_RATE
+ measured_at=1613547098 updated_at=1613547098 pid_error=11.275680184 pid_error_sum=11.275680184 pid_bw=23255048 pid_delta=11.0140582849 circ_fail=0.0
- [snip]
+sbws does not have ``measured_at`` and ``updated_at`` either.
- # old measurements are probably
- # better than no measurements. We may not
- # measure hibernating routers for days.
- # This filter is just to remove REALLY old files
- if time.time() - timestamp > MAX_AGE:
+Currently the scaled bandwidth in Torflow does not depend on those extra values
+and they seem to be just informative.
1
0

[translation/communitytpo-contentspot] https://gitweb.torproject.org/translation.git/commit/?h=communitytpo-contentspot
by translation@torproject.org 26 Feb '21
by translation@torproject.org 26 Feb '21
26 Feb '21
commit 79dd100c6e338d449f17067b8c47fdbde7506941
Author: Translation commit bot <translation(a)torproject.org>
Date: Fri Feb 26 10:15:13 2021 +0000
https://gitweb.torproject.org/translation.git/commit/?h=communitytpo-conten…
---
contents+ka.po | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/contents+ka.po b/contents+ka.po
index c4bf15963f..0cdcea7134 100644
--- a/contents+ka.po
+++ b/contents+ka.po
@@ -13745,6 +13745,10 @@ msgid ""
"prepended with '#', while commands to be run as user with '$' resembling the"
" standard prompt in a terminal."
msgstr ""
+"ქვემოთ ყველა ბრძანება, რომელიც საჭიროებს ძირეული მომხმარებლის უფლებით "
+"გაეშვას, როგორც apt და dpkg, წარმოდგენილია ნიშანით '#', ხოლო ბრძანებები "
+"რომლებიც აღნიშნულია '$' მომხმარებლით, მიუთითებს რომ ჩვეულებრივ ტერმინალში "
+"იწერება."
#: https//community.torproject.org/onion-services/setup/install/
#: (content/onion-services/setup/install/contents+en.lrpage.body)
@@ -13753,6 +13757,9 @@ msgid ""
" -i. Note that sudo asks for your user password, while su expects the root "
"password of your system."
msgstr ""
+"ძირეული მომხმარებლის ტერმინალის გასახსნელად რამდენიმე გზაა: sudo su, ან sudo"
+" -i, ან კიდევ su -i. გაითვალისწინეთ, რომ sudo ითხოვს მომხმარებლის პაროლს, "
+"მაშინ როცა su მოელის სისტემის ძირეულ პაროლს."
#: https//community.torproject.org/onion-services/setup/install/
#: (content/onion-services/setup/install/contents+en.lrpage.body)
@@ -14008,6 +14015,9 @@ msgid ""
"[libevent](http://www.monkey.org/~provos/libevent/), and make sure you have "
"openssl and zlib (including the -devel packages if applicable)."
msgstr ""
+"თუ წყაროს კოდიდან აწყობთ, ჯერ დააყენეთ "
+"[libevent](http://www.monkey.org/~provos/libevent/), შემდეგ კი დარწმუნდით "
+"რომ გაქვთ openssl და zlib (მათ შორის -devel კრებულები, თუ შეესაბამება)."
#: https//community.torproject.org/onion-services/setup/install/
#: (content/onion-services/setup/install/contents+en.lrpage.body)
@@ -14031,6 +14041,10 @@ msgid ""
" install` (as root if necessary) to install it into /usr/local/, and then "
"you can start it just by running tor."
msgstr ""
+"ახლა კი შეგიძლიათ გაუშვათ tor როგორც src/app/tor (0.4.3.x და ახლებზე), ან "
+"შეგიძლიათ გაუშვათ `make install` (ძირეულად, თუ საჭიროა) რომ დააყენოთ "
+"მისამართზე /usr/local/, შემდეგ კი შეგეძლებათ ჩართოთ, უბრალოდ Tor-ის "
+"გაშვებით."
#: https//community.torproject.org/relay/setup/guard/freebsd/
#: (content/relay-operations/technical-setup/guard/freebsd/contents+en.lrpage.title)
@@ -14061,6 +14075,11 @@ msgid ""
"about it. Follow the instructions to enable [automatic software "
"updates](updates) for your operating system."
msgstr ""
+"ერთ-ერთი მნიშვნელოვანი რამ, რაც უზრუნველყოფს თქვენი გადამცემის დაცულობას, "
+"არის უსაფრთხოების განახლებების დროულად დაყენება, საუკეთესო გადაწყვეტა იქნება"
+" ავტომატურად, ისე რომ შეგეძლებათ აღარც იღელვოთ ამაზე. მიჰყევით მითითებებს "
+"[ავტომატური პროგრამული განახლებების](updates) ჩასართავად, თქვენს საოპერაციო "
+"სისტემაზე."
#: https//community.torproject.org/relay/setup/guard/freebsd/
#: (content/relay-operations/technical-setup/guard/freebsd/contents+en.lrpage.body)
@@ -14155,6 +14174,8 @@ msgid ""
"We are keeping the original setting used by `pkg` but setting a new one that"
" will override it."
msgstr ""
+"თავდაპირველი პარამეტრი ნარჩუნდება, რომელსაც `pkg` იყენებს, მაგრამ ეთითება "
+"ახალი, რომელიც ანაცვლებს."
#: https//community.torproject.org/relay/setup/guard/freebsd/
#: (content/relay-operations/technical-setup/guard/freebsd/contents+en.lrpage.body)
@@ -14162,6 +14183,8 @@ msgid ""
"So we set up a new directory, and then create a configuration file to "
"override what we need."
msgstr ""
+"ასე რომ, მოეწყობა ახალი საქაღალდე და შემდეგ შეიქმნება გასამართი ფაილი იმის "
+"ჩასანაცვლებლად, რაც გვჭირდება."
#: https//community.torproject.org/relay/setup/guard/freebsd/
#: (content/relay-operations/technical-setup/guard/freebsd/contents+en.lrpage.body)
@@ -17008,6 +17031,9 @@ msgid ""
"Note to Tor relay operators: In this litigious era, anyone providing routing"
" services may face copyright complaints for transmitted content."
msgstr ""
+"გაითვალისწინეთ Tor-გადამცემის გამშვებებმა: ამ დავებისა და გარჩევების ხანაში,"
+" ნებისმიერი, რომელიც უზრუნველყოფს კავშირის გატარებას, შეიძლება წააწყდეს ამ "
+"გატარებულ მასალების საავტორო უფლებებზე საჩივრებს."
#: https//community.torproject.org/relay/community-resources/eff-tor-legal-faq/tor-dmca-response/
#: (content/relay-operations/community-resources/eff-tor-legal-faq/tor-dmca-response/contents+en.lrpage.body)
@@ -17015,6 +17041,9 @@ msgid ""
"Fortunately, copyright law should provide protections from many of them both"
" to you and to your upstream provider."
msgstr ""
+"საბედნიეროდ, საავტორო უფლებების კანონების უმეტესობაში განსაზღვრულია ხოლმე "
+"ხელშეუხებლობის პირობები, როგორც თქვენი, ასევე თქვენი მომწოდებლის "
+"სასარგებლოდ."
#: https//community.torproject.org/relay/community-resources/eff-tor-legal-faq/tor-dmca-response/
#: (content/relay-operations/community-resources/eff-tor-legal-faq/tor-dmca-response/contents+en.lrpage.body)
@@ -17023,6 +17052,9 @@ msgid ""
"this template to write a response, though you will need to customize it to "
"your situation."
msgstr ""
+"თუ თქვენი ინტერნეტის განმთავსებელი გადმოამისამართებს საავტორო უფლებების "
+"დარღვევის საჩივარს თქვენთან, შეგიძლია გამოიყენოთ ეს ნიმუში პასუხის "
+"დასაწერად, თუმცა დაგჭირდებათ ჯერ უკეთ მოარგოთ თქვენს გარემოებებს."
#: https//community.torproject.org/relay/community-resources/eff-tor-legal-faq/tor-dmca-response/
#: (content/relay-operations/community-resources/eff-tor-legal-faq/tor-dmca-response/contents+en.lrpage.body)
@@ -17036,6 +17068,9 @@ msgid ""
"resources/tor-abuse-templates/) to help you respond to other types of abuse "
"complaints, too.)"
msgstr ""
+"(Tor-პროექტს აქვს [ბოროტად გამოყენების ნიმუშთა კრებულები](/relay/community-"
+"resources/tor-abuse-templates/), რომლებიც დაგეხმარებათ პასუხი გასცეთ სხვა "
+"სახის საჩივრებსაც.)"
#: https//community.torproject.org/relay/community-resources/eff-tor-legal-faq/tor-dmca-response/
#: (content/relay-operations/community-resources/eff-tor-legal-faq/tor-dmca-response/contents+en.lrpage.body)
@@ -17062,6 +17097,9 @@ msgid ""
"Whether and how you should respond when you or your ISP has received a "
"copyright notice will turn on the particular facts of your situation."
msgstr ""
+"უპასუხოთ თუ არა და როგორ უპასუხოთ, როცა თქვენ ან თქვენი ინტერნეტის "
+"მომწოდებელი მიიღებს საავტორო უფლებებზე უწყებას, დამოკიდებულია, არსებული "
+"ვითარების ცალკეულ საკითხებზე."
#: https//community.torproject.org/relay/community-resources/eff-tor-legal-faq/tor-dmca-response/
#: (content/relay-operations/community-resources/eff-tor-legal-faq/tor-dmca-response/contents+en.lrpage.body)
@@ -17069,6 +17107,8 @@ msgid ""
"This template is intended as a starting point, but you should tailor it to "
"your own circumstances."
msgstr ""
+"ეს ნიმუში გამოდგება დასაწყისისთვის, მაგრამ საჭიროა მოარგოთ საკუთარ "
+"გარემოებებს."
#: https//community.torproject.org/relay/community-resources/eff-tor-legal-faq/tor-dmca-response/
#: (content/relay-operations/community-resources/eff-tor-legal-faq/tor-dmca-response/contents+en.lrpage.body)
1
0

[translation/communitytpo-contentspot] https://gitweb.torproject.org/translation.git/commit/?h=communitytpo-contentspot
by translation@torproject.org 26 Feb '21
by translation@torproject.org 26 Feb '21
26 Feb '21
commit dbf26784698af0ac6b073ceda9c3b2557a4bf7f1
Author: Translation commit bot <translation(a)torproject.org>
Date: Fri Feb 26 09:45:13 2021 +0000
https://gitweb.torproject.org/translation.git/commit/?h=communitytpo-conten…
---
contents+ka.po | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/contents+ka.po b/contents+ka.po
index ba70421a09..c4bf15963f 100644
--- a/contents+ka.po
+++ b/contents+ka.po
@@ -13622,6 +13622,9 @@ msgid ""
"https) by default, so it provisions your TLS certificate and takes care of "
"HTTP-to-HTTPS redirection for you."
msgstr ""
+"Caddy-შესაძლებლობები [ავტომატური HTTPS](https://caddyserver.com/docs"
+"/automatic-https) ნაგულისხმევად, ანუ იგი უზრუნველყოფს თქვენს TLS-სერტიფიკატს"
+" და ზრუნავს HTTP-იდან HTTPS-სკენ გადამისამართებაზე."
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13629,6 +13632,8 @@ msgid ""
"If you're using Caddy 2, to include an Onion-Location header, add the "
"following declaration in your Caddyfile:"
msgstr ""
+"თუ გიყენიათ Caddy 2, რომ დაურთოთ Onion-მდებარეობის თავსართი, დაამატეთ "
+"შემდეგი განაცხადი Caddy-ფაილში:"
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13641,6 +13646,8 @@ msgid ""
"If you're running a static site and have the onion address in a "
"`$TOR_HOSTNAME` environment variable, your Caddyfile will look like this:"
msgstr ""
+"თუ გაშვებული გაქვთ უცვლელი საიტი და მითითებული გაქვთ Onion-მისამართი "
+"`$TOR_HOSTNAME` გარემოს ცვლადად, თქვენი Caddy-ფაილი უნდა გამოიყურებოდეს ასე:"
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13665,12 +13672,12 @@ msgstr "file_server"
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
msgid "**Testing it out:** Test it out with:"
-msgstr ""
+msgstr "**შემოწმება:** გადასამოწმებლად:"
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
msgid "### Using an HTML `<meta>` attribute"
-msgstr ""
+msgstr "### გამოიყენეთ HTML `<meta>` მახასიათებელი"
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13678,6 +13685,8 @@ msgid ""
"The identical behaviour of Onion-Location includes the option of defining it"
" as a HTML `<meta>` http-equiv attribute."
msgstr ""
+"მსგავსი ქცევა Onion-მდებარეობისა, მოიცავს შესაძლებლობას განისაზღვროს HTML "
+"`<meta>` http-equiv თვისების სახით."
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13686,6 +13695,9 @@ msgid ""
"Location by modifying the served HTML content instead of adding a new HTTP "
"header."
msgstr ""
+"ეს შეიძლება გამოიყენოს ვებსაიტებმა, რომლებიც ამჯობინებს (ან საჭიროებს) "
+"განსაზღვროს Onion-მდებარეობა მომსახურე HTML-შიგთავსის გადაკეთებით, ნაცვლად "
+"ახალი HTTP-თავსართის დამატებისა."
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13695,6 +13707,11 @@ msgid ""
"/>` added in the HTML head element of the webpage. Replace `<your-onion-"
"service-address.onion>` with the onion service that you want to redirect."
msgstr ""
+"Onion-მდებარეობის თავსართი უნდა შეესაბამებოდეს `<meta http-equiv=\"onion-"
+"location\" content=\"http://<your-onion-service-address>.onion\" />` "
+"მნიშვნელობას, დამატებულს, საიტის HTML-ის head-ელემენტში. ჩაანაცვლეთ `<your-"
+"onion-service-address.onion>` Onion-მომსახურებით, რომლის გადამისამართებაც "
+"გსურთ."
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13707,6 +13724,8 @@ msgid ""
"Read the [Onion-Location spec](https://gitweb.torproject.org/tor-browser-"
"spec.git/tree/proposals/100-onion-location-header.txt)."
msgstr ""
+"გაეცანით [Onion-მდებარეობის მახასიათებლებს](https://gitweb.torproject.org"
+"/tor-browser-spec.git/tree/proposals/100-onion-location-header.txt)."
#: https//community.torproject.org/onion-services/setup/install/
#: (content/onion-services/setup/install/contents+en.lrpage.title)
1
0

[translation/communitytpo-contentspot] https://gitweb.torproject.org/translation.git/commit/?h=communitytpo-contentspot
by translation@torproject.org 26 Feb '21
by translation@torproject.org 26 Feb '21
26 Feb '21
commit fb571878ed3265ef894918e7d79abb420c8e610b
Author: Translation commit bot <translation(a)torproject.org>
Date: Fri Feb 26 09:15:20 2021 +0000
https://gitweb.torproject.org/translation.git/commit/?h=communitytpo-conten…
---
contents+ka.po | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/contents+ka.po b/contents+ka.po
index 11448eabf9..ba70421a09 100644
--- a/contents+ka.po
+++ b/contents+ka.po
@@ -13048,6 +13048,10 @@ msgid ""
"services/setup/), be careful of letting your web server reveal identifying "
"information about you, your computer, or your location."
msgstr ""
+"- როგორც აღნიშნულია [აქ](https://community.torproject.org/onion-"
+"services/setup/), გამოიჩინეთ წინდახედულობა, როცა ვებსერვერს უმჟღავნებთ "
+"ამოსაცნობ მონაცემებს თქვენ შესახებ, თქვენი კომპიუტერის ან თქვენი მდებარეობის"
+" თაობაზე."
#: https//community.torproject.org/onion-services/advanced/opsec/
#: (content/onion-services/advanced/opsec/contents+en.lrpage.body)
@@ -13070,7 +13074,7 @@ msgstr ""
#: https//community.torproject.org/onion-services/advanced/opsec/
#: (content/onion-services/advanced/opsec/contents+en.lrpage.body)
msgid "This leaks information to an observant adversary."
-msgstr ""
+msgstr "ეს უმჟღავნებს მონაცემებს ჩასაფრებულ მოწინააღმდეგეებს."
#: https//community.torproject.org/onion-services/advanced/opsec/
#: (content/onion-services/advanced/opsec/contents+en.lrpage.body)
@@ -13098,6 +13102,9 @@ msgid ""
"The most prominent attacks are building a profile of the onion service's "
"availability and matching induced traffic patterns."
msgstr ""
+"ყველაზე ხშირია შეტევებისთვის დახასიათების შედგენა Onion-მომსახურების "
+"ხელმისაწვდომობის შესახებ, მონაცემების გატარებაზე ხელოვნურ ზეგავლენასთან "
+"თანხლებით."
#: https//community.torproject.org/onion-services/advanced/opsec/
#: (content/onion-services/advanced/opsec/contents+en.lrpage.body)
@@ -13180,12 +13187,16 @@ msgstr ""
msgid ""
"* The webpage defining the Onion-Location header must be served over HTTPS."
msgstr ""
+"* ვებგვერდი, რომლითაც განისაზღვრება Onion-მდებარეობის თავსართი, "
+"უზრუნველყოფილი უნდა იყოს HTTPS-ით."
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
msgid ""
"* The webpage defining the Onion-Location header must not be an onion site."
msgstr ""
+"* ვებგვერდი, რომლითაც განისაზღვრება Onion-მდებარეობის თავსართი, არ უნდა "
+"წარმოადგენდეს Onion-საიტს."
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13213,6 +13224,9 @@ msgid ""
"To configure this header in Apache 2.2 or above, you will need to enable a "
"`headers` and `rewrite` modules and edit the website Virtual Host file."
msgstr ""
+"ამ თავსართის გასამართად Apache 2.2 და ზედა ვერსიებში, საჭიროა ჩართოთ "
+"`headers` და `rewrite` მოდულები, ამასთან ჩაასწოროთ ვებსაიტის Virtual Host "
+"ფაილი."
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13244,6 +13258,7 @@ msgstr ""
msgid ""
"Header set Onion-Location \"http://your-onion-address.onion%{REQUEST_URI}s\""
msgstr ""
+"Header set Onion-Location \"http://your-onion-address.onion%{REQUEST_URI}s\""
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13253,6 +13268,10 @@ msgid ""
"URI](https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html), such as "
"\"/index.html\"."
msgstr ""
+"სადაც `your-onion-address.onion` არის Onion-მომსახურების მისამართი, რომელიც "
+"გსურთ გადამისამართდეს და `{REQUEST_URI}` არის [მიმართულების აღმნიშვნელი "
+"მოთხოვნილი URI-ს](https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html), "
+"როგორიცაა \"/index.html\"."
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13316,6 +13335,8 @@ msgid ""
"To test if Onion-Location is working, fetch the website HTTP headers, for "
"example:"
msgstr ""
+"შესამოწმებლად, მუშაობს თუ არა Onion-მდებარეობა, გამოითხოვეთ ვებსაიტის HTTP-"
+"თავსართები, მაგალითად:"
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13333,6 +13354,8 @@ msgid ""
"Or open the website in Tor Browser and a purple pill will appear in the "
"address bar."
msgstr ""
+"ან გახსენით ვებსაიტი Tor-ბრაუზერი და იისფერი ნიშანი გამოჩნდება მისამართების "
+"ველში."
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13353,6 +13376,8 @@ msgstr ""
msgid ""
"**Step 1.** Create an Onion service by setting the following in `torrc`:"
msgstr ""
+"**ნაბიჯი 1.** შექმენით Onion-მომსახურება შემდეგი პარამეტრების გამართვით "
+"ფაილში `torrc`:"
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
@@ -13574,6 +13599,8 @@ msgid ""
"To test if the Onion-Location is working, fetch the web site HTTP headers, "
"for example:"
msgstr ""
+"შესამოწმებლად, მუშაობს თუ არა Onion-მდებარეობა, გამოითხოვეთ ვებსაიტის HTTP-"
+"თავსართები, მაგალითად:"
#: https//community.torproject.org/onion-services/advanced/onion-location/
#: (content/onion-services/advanced/onion-location/contents+en.lrpage.body)
1
0