commit f3044b212baab32583db8ce107796d1b2e2a705b Author: Karsten Loesing karsten.loesing@gmx.net Date: Thu Jul 28 23:00:17 2011 -0400
Add top-10 country by possible censorship events.
Implements some more of #2718. --- rserve/tables.R | 39 ++++++++++++++++++++ .../ernie/web/GraphsSubpagesServlet.java | 3 +- .../ernie/web/TableParameterChecker.java | 1 + web/WEB-INF/users.jsp | 37 ++++++++++++++++++- 4 files changed, 78 insertions(+), 2 deletions(-)
diff --git a/rserve/tables.R b/rserve/tables.R index 725bc31..6d3b5fb 100644 --- a/rserve/tables.R +++ b/rserve/tables.R @@ -30,3 +30,42 @@ write_direct_users <- function(start, end, path) { write.csv(d, path, quote = FALSE, row.names = FALSE) }
+write_censorship_events <- function(start, end, path) { + drv <- dbDriver("PostgreSQL") + con <- dbConnect(drv, user = dbuser, password = dbpassword, dbname = db) + q <- paste("SELECT date, country, r, bwp, brn, bwn, brp, bwr, brr ", + "FROM user_stats WHERE date >= '", start, "' AND date <= '", end, + "' AND date < (SELECT MAX(date) FROM user_stats) - 1", + sep = "") + rs <- dbSendQuery(con, q) + u <- fetch(rs, n = -1) + dbDisconnect(con) + dbUnloadDriver(drv) + u <- data.frame(date = u$date, country = u$country, + users = u$r * (u$bwp * u$brn / u$bwn - u$brp) / + (u$bwr * u$brn / u$bwn - u$brr) / 10) + dates <- seq(from = as.Date(start, "%Y-%m-%d"), + to = as.Date(end, "%Y-%m-%d"), by="1 day") + missing <- setdiff(dates, u$date) + r <- read.csv( + "/srv/metrics.torproject.org/web/detector/direct-users-ranges.csv", + stringsAsFactors = FALSE) + r <- r[r$date >= start & r$date <= end, + c("date", "country", "minusers", "maxusers")] + r <- cast(rbind(melt(u, id.vars = c("date", "country")), + melt(r, id.vars = c("date", "country")))) + r <- na.omit(r[r$users < r$minusers | r$users > r$maxusers, ]) + r <- data.frame(date = r$date, country = r$country, + upturn = ifelse(r$users > r$maxusers, 1, 0), + downturn = ifelse(r$users < r$minusers, 1, 0)) + r <- aggregate(r[, c("upturn", "downturn")], + by = list(country = r$country), sum) + r <- r[order(r$downturn, r$upturn, decreasing = TRUE), ] + r <- r[1:10, ] + r <- data.frame(cc = r$country, + country = sub('the ', '', countrynames(as.character(r$country))), + downturns = r$downturn, + upturns = r$upturn) + write.csv(r, path, quote = FALSE, row.names = FALSE) +} + diff --git a/src/org/torproject/ernie/web/GraphsSubpagesServlet.java b/src/org/torproject/ernie/web/GraphsSubpagesServlet.java index e3845cf..c7f3056 100644 --- a/src/org/torproject/ernie/web/GraphsSubpagesServlet.java +++ b/src/org/torproject/ernie/web/GraphsSubpagesServlet.java @@ -34,7 +34,8 @@ public class GraphsSubpagesServlet extends HttpServlet { this.availableGraphsSubpageTables = new HashMap<String, Set<String>>(); this.availableGraphsSubpageTables.put("users.html", - new HashSet<String>(Arrays.asList("direct-users".split(",")))); + new HashSet<String>(Arrays.asList( + "direct-users,censorship-events".split(","))));
this.knownCountries = Countries.getInstance().getCountryList(); } diff --git a/src/org/torproject/ernie/web/TableParameterChecker.java b/src/org/torproject/ernie/web/TableParameterChecker.java index 9bf1c33..5b6f627 100644 --- a/src/org/torproject/ernie/web/TableParameterChecker.java +++ b/src/org/torproject/ernie/web/TableParameterChecker.java @@ -40,6 +40,7 @@ public class TableParameterChecker {
this.availableTables = new HashMap<String, String>(); this.availableTables.put("direct-users", "start,end,filename"); + this.availableTables.put("censorship-events", "start,end,filename");
this.knownParameterValues = new HashMap<String, String>(); } diff --git a/web/WEB-INF/users.jsp b/web/WEB-INF/users.jsp index b378af1..bb4e11c 100644 --- a/web/WEB-INF/users.jsp +++ b/web/WEB-INF/users.jsp @@ -24,6 +24,7 @@ out of a few hundred directory mirrors to save bandwidth of the directory authorities. The following graphs show an estimate of recurring Tor users based on the requests seen by a few dozen directory mirrors.</p> <a name="direct-users"></a> +<p><b>Daily directly connecting users:</b></p> <img src="direct-users.png${direct_users_url}" width="576" height="360" alt="Direct users graph"> <form action="users.html#direct-users"> @@ -60,6 +61,7 @@ based on the requests seen by a few dozen directory mirrors.</p> </div> </form> <a name="direct-users-table"></a> +<p><b>Top-10 countries by directly connecting users:</b></p> <table> <tr> <th>Country</th> @@ -88,7 +90,40 @@ based on the requests seen by a few dozen directory mirrors.</p> </p> </div> </form> -<p><a href="csv/direct-users.csv">CSV</a> file containing all data.</p> +<a name="censorship-events"></a> +<p><b>Top-10 countries by possible censorship events (BETA):</b></p> +<table> + <tr> + <th>Country</th> + <th>Downturns</th> + <th>Upturns</th> + </tr> + <c:forEach var="row" items="${censorship_events_tabledata}"> + <tr> + <td><a href="users.html?graph=direct-users&country=${row['cc']}&events=on#direct-users">${row['country']}</a> </td> + <td>${row['downturns']}</td> + <td>${row['upturns']}</td> + </tr> + </c:forEach> +</table> +<br> +<form action="users.html#censorship-events"> + <div class="formrow"> + <input type="hidden" name="table" value="censorship-events"> + <p> + <label>Start date (yyyy-mm-dd):</label> + <input type="text" name="start" size="10" + value="<c:choose><c:when test="${fn:length(censorship_events_start) == 0}">${default_start_date}</c:when><c:otherwise>${censorship_events_start[0]}</c:otherwise></c:choose>"> + <label>End date (yyyy-mm-dd):</label> + <input type="text" name="end" size="10" + value="<c:choose><c:when test="${fn:length(censorship_events_end) == 0}">${default_end_date}</c:when><c:otherwise>${censorship_events_end[0]}</c:otherwise></c:choose>"> + </p><p> + <input class="submit" type="submit" value="Update table"> + </p> + </div> +</form> +<p><a href="csv/direct-users.csv">CSV</a> file containing daily directly +connecting users by country.</p> <p><a href="csv/monthly-users-peak.csv">CSV</a> file containing peak daily Tor users (direct and bridge) per month by country.</p> <p><a href="csv/monthly-users-average.csv">CSV</a> file containing average