tor-commits
Threads by month
- ----- 2025 -----
- July
- 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
January 2017
- 22 participants
- 1796 discussions

[metrics-web/master] Avoid line breaks between checkboxes and labels.
by karsten@torproject.org 09 Jan '17
by karsten@torproject.org 09 Jan '17
09 Jan '17
commit 42101f8b41f069cf98e53c3e626550fde2fd7f47
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Mon Jan 9 20:45:37 2017 +0100
Avoid line breaks between checkboxes and labels.
Fixes #21175.
---
website/web/WEB-INF/graph.jsp | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/website/web/WEB-INF/graph.jsp b/website/web/WEB-INF/graph.jsp
index 4be02bd..59261a6 100644
--- a/website/web/WEB-INF/graph.jsp
+++ b/website/web/WEB-INF/graph.jsp
@@ -75,8 +75,9 @@
<p>
<b>Relay flags:</b>
<c:forEach var="row" items="${flag}">
- <input type="checkbox" name="flag" value="${row[0]}" id="flag_${row[0]}"${row[1]}>
- <label class="checkbox-label" for="flag_${row[0]}">${row[0]}</label>
+ <label class="checkbox-label">
+ <input type="checkbox" name="flag" value="${row[0]}"${row[1]}> ${row[0]}
+ </label>
</c:forEach>
</p>
</c:if>
@@ -105,8 +106,9 @@
<p>
<b>Source:</b>
<c:forEach var="row" items="${transport}">
- <input type="checkbox" name="transport" value="${row[0]}" id="transport_${row[0]}"${row[1]}>
- <label class="checkbox-label" for="transport_${row[0]}">${row[2]}</label>
+ <label class="checkbox-label">
+ <input type="checkbox" name="transport" value="${row[0]}"${row[1]}> ${row[2]}
+ </label>
</c:forEach>
</p>
</c:if>
1
0

[metrics-web/master] Adapt the wording for tables and link pages.
by karsten@torproject.org 09 Jan '17
by karsten@torproject.org 09 Jan '17
09 Jan '17
commit 7ca94a0a0bc212607577cae43e6acb441692c129
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Mon Jan 9 18:16:19 2017 +0100
Adapt the wording for tables and link pages.
s/The following/This/
---
website/etc/metrics.json | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/website/etc/metrics.json b/website/etc/metrics.json
index 1ba21a4..f7666be 100644
--- a/website/etc/metrics.json
+++ b/website/etc/metrics.json
@@ -167,7 +167,7 @@
"id": "userstats-relay-table",
"title": "Top-10 countries by relay users",
"type": "Table",
- "description": "<p>The following table shows the top-10 countries by estimated number of directly-connecting <a href=\"glossary.html#client\">clients</a>. These numbers are derived from directory requests counted on <a href=\"glossary.html#directory-authority\">directory authorities</a> and <a href=\"glossary.html#directory-mirror\">mirrors</a>. Relays resolve client IP addresses to country codes, so that numbers are available for most countries. For further details see these <a href=\"https://gitweb.torproject.org/metrics-web.git/tree/doc/users-q-and-a.txt\">questions and answers about user statistics</a>.</p>",
+ "description": "<p>This table shows the top-10 countries by estimated number of directly-connecting <a href=\"glossary.html#client\">clients</a>. These numbers are derived from directory requests counted on <a href=\"glossary.html#directory-authority\">directory authorities</a> and <a href=\"glossary.html#directory-mirror\">mirrors</a>. Relays resolve client IP addresses to country codes, so that numbers are available for most countries. For further details see these <a href=\"https://gitweb.torproject.org/metrics-web.git/tree/doc/users-q-and-a.txt\">questions and answers about user statistics</a>.</p>",
"function": "write_userstats_relay",
"parameters": [
"start",
@@ -189,7 +189,7 @@
"id": "userstats-censorship-events",
"title": "Top-10 countries by possible censorship events",
"type": "Table",
- "description": "<p>The following table shows the top-10 countries by possible censorship events, as obtained from an anomaly-based censorship-detection system (for more details, see this <a href=\"https://research.torproject.org/techreports/detector-2011-09-09.pdf\">technical report</a>). For further details see these <a href=\"https://gitweb.torproject.org/metrics-web.git/tree/doc/users-q-and-a.txt\">questions and answers about user statistics</a>.</p>",
+ "description": "<p>This table shows the top-10 countries by possible censorship events, as obtained from an anomaly-based censorship-detection system (for more details, see this <a href=\"https://research.torproject.org/techreports/detector-2011-09-09.pdf\">technical report</a>). For further details see these <a href=\"https://gitweb.torproject.org/metrics-web.git/tree/doc/users-q-and-a.txt\">questions and answers about user statistics</a>.</p>",
"function": "write_userstats_censorship_events",
"parameters": [
"start",
@@ -228,7 +228,7 @@
"id": "userstats-bridge-table",
"title": "Top-10 countries by bridge users",
"type": "Table",
- "description": "<p>The following table shows the top-10 countries by estimated number of <a href=\"glossary.html#client\">clients</a> connecting via <a href=\"glossary.html#bridge\">bridges</a>. These numbers are derived from directory requests counted on bridges. Bridges resolve client IP addresses of incoming directory requests to country codes, so that numbers are available for most countries. For further details see these <a href=\"https://gitweb.torproject.org/metrics-web.git/tree/doc/users-q-and-a.txt\">questions and answers about user statistics</a>.</p>",
+ "description": "<p>This table shows the top-10 countries by estimated number of <a href=\"glossary.html#client\">clients</a> connecting via <a href=\"glossary.html#bridge\">bridges</a>. These numbers are derived from directory requests counted on bridges. Bridges resolve client IP addresses of incoming directory requests to country codes, so that numbers are available for most countries. For further details see these <a href=\"https://gitweb.torproject.org/metrics-web.git/tree/doc/users-q-and-a.txt\">questions and answers about user statistics</a>.</p>",
"function": "write_userstats_bridge",
"parameters": [
"start",
@@ -395,12 +395,12 @@
"id": "uptimes",
"title": "Monthly uptime of relays",
"type": "Link",
- "description": "<p>The following image illustrates the uptime of all known <a href=\"glossary.html#relay\">relays</a> in a given month. Each row of pixels denotes one <a href=\"glossary.html#consensus\">consensus</a> (that is, one hour), and each column denotes one relay. Each pixel denotes if a given relay was online or offline at a given hour: black means online, white means offline, and red highlights relays with identical uptime patterns. The complete image gallery can be found on <a href=\"https://nymity.ch/sybilhunting/uptime-visualisation/\">Philipp Winter's homepage</a>.</p><p><a href=\"https://nymity.ch/sybilhunting/uptime-visualisation/\"><img src=\"images/uptimes.jpg\" alt=\"Monthly uptime of relays\"></a></p>"
+ "description": "<p>This image illustrates the uptime of all known <a href=\"glossary.html#relay\">relays</a> in a given month. Each row of pixels denotes one <a href=\"glossary.html#consensus\">consensus</a> (that is, one hour), and each column denotes one relay. Each pixel denotes if a given relay was online or offline at a given hour: black means online, white means offline, and red highlights relays with identical uptime patterns. The complete image gallery can be found on <a href=\"https://nymity.ch/sybilhunting/uptime-visualisation/\">Philipp Winter's homepage</a>.</p><p><a href=\"https://nymity.ch/sybilhunting/uptime-visualisation/\"><img src=\"images/uptimes.jpg\" alt=\"Monthly uptime of relays\"></a></p>"
},
{
"id": "networkchurn",
"title": "Network churn rate by relay flag",
"type": "Link",
- "description": "<p>The following image shows the churn rate of the Tor network by <a href=\"glossary.html#relay-flag\">relay flag</a> in a given month. The churn rate, a value in the interval <b>[0,1]</b>, captures the rate of <a href=\"glossary.html#relay\">relays</a> joining and leaving the network from one <a href=\"glossary.html#consensus\">consensus</a> to the next (that is, within one hour). The complete image gallery can be found on <a href=\"https://nymity.ch/sybilhunting/churn-values/\">Philipp Winter's homepage</a>.</p><p><a href=\"https://nymity.ch/sybilhunting/churn-values/\"><img src=\"images/networkchurn.png\" alt=\"Network churn rate by relay flag\"></a></p>"
+ "description": "<p>This image shows the churn rate of the Tor network by <a href=\"glossary.html#relay-flag\">relay flag</a> in a given month. The churn rate, a value in the interval <b>[0,1]</b>, captures the rate of <a href=\"glossary.html#relay\">relays</a> joining and leaving the network from one <a href=\"glossary.html#consensus\">consensus</a> to the next (that is, within one hour). The complete image gallery can be found on <a href=\"https://nymity.ch/sybilhunting/churn-values/\">Philipp Winter's homepage</a>.</p><p><a href=\"https://nymity.ch/sybilhunting/churn-values/\"><img src=\"images/networkchurn.png\" alt=\"Network churn rate by relay flag\"></a></p>"
}
]
1
0

[metrics-web/master] Add another navigation bar to Metrics subpages.
by karsten@torproject.org 09 Jan '17
by karsten@torproject.org 09 Jan '17
09 Jan '17
commit e09b16a25de6c574778ef3d1a1afdf5d2e3440f3
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Tue Dec 13 15:59:08 2016 +0100
Add another navigation bar to Metrics subpages.
---
website/etc/categories.json | 12 ++++++------
.../org/torproject/metrics/web/GraphServlet.java | 12 ++++++++++++
.../org/torproject/metrics/web/IndexServlet.java | 17 +++++++++++++++++
website/web/WEB-INF/about.jsp | 1 +
website/web/WEB-INF/bubbles.jsp | 1 +
website/web/WEB-INF/data.jsp | 1 +
website/web/WEB-INF/error.jsp | 1 +
website/web/WEB-INF/graph.jsp | 7 ++++++-
website/web/WEB-INF/index.jsp | 21 ++++++---------------
website/web/WEB-INF/link.jsp | 1 +
website/web/WEB-INF/research.jsp | 1 +
website/web/WEB-INF/sources.jsp | 1 +
website/web/WEB-INF/table.jsp | 3 ++-
website/web/WEB-INF/tools.jsp | 1 +
14 files changed, 57 insertions(+), 23 deletions(-)
diff --git a/website/etc/categories.json b/website/etc/categories.json
index 563b662..fe01905 100644
--- a/website/etc/categories.json
+++ b/website/etc/categories.json
@@ -2,7 +2,7 @@
{
"id": "clients",
"header": "Users",
- "description": "<p>Where are Tor users from? How do they connect to Tor?</p>",
+ "description": "Where are Tor users from? How do they connect to Tor?",
"metrics": [
"userstats-relay-country",
"userstats-bridge-country",
@@ -17,7 +17,7 @@
{
"id": "servers",
"header": "Relays and Bridges",
- "description": "<p>How many relays and bridges are online? What do we know about them?</p>",
+ "description": "How many relays and bridges are online? What do we know about them?",
"metrics": [
"networksize",
"relayflags",
@@ -28,7 +28,7 @@
{
"id": "traffic",
"header": "Traffic",
- "description": "<p>How much traffic can the Tor network handle? How much traffic is there?</p>",
+ "description": "How much traffic can the Tor network handle? How much traffic is there?",
"metrics": [
"bandwidth",
"bandwidth-flags",
@@ -41,7 +41,7 @@
{
"id": "performance",
"header": "Performance",
- "description": "<p>How fast and reliable is the Tor network?</p>",
+ "description": "How fast and reliable is the Tor network?",
"metrics": [
"torperf",
"torperf-failures",
@@ -51,7 +51,7 @@
{
"id": "onion-services",
"header": "Onion Services",
- "description": "<p>How many onion services are there? How much traffic do they pull?</p>",
+ "description": "How many onion services are there? How much traffic do they pull?",
"metrics": [
"hidserv-dir-onions-seen",
"hidserv-rend-relayed-cells",
@@ -61,7 +61,7 @@
{
"id": "downloads",
"header": "Downloads (coming soon)",
- "description": "<p>How many downloads of Tor applications are there? How many updates?</p>",
+ "description": "How many downloads of Tor applications are there? How many updates?",
"metrics": []
}
]
diff --git a/website/src/org/torproject/metrics/web/GraphServlet.java b/website/src/org/torproject/metrics/web/GraphServlet.java
index 3a73fa5..5e90499 100644
--- a/website/src/org/torproject/metrics/web/GraphServlet.java
+++ b/website/src/org/torproject/metrics/web/GraphServlet.java
@@ -134,6 +134,18 @@ public class GraphServlet extends MetricServlet {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
+ List<String[]> categories = new ArrayList<String[]>();
+ for (Category category :
+ ContentProvider.getInstance().getCategoriesList()) {
+ if (category.getMetrics().isEmpty()
+ || this.categories.get(requestedId).equals(category)) {
+ categories.add(new String[] { "", category.getHeader() });
+ } else {
+ categories.add(new String[] { category.getMetrics().get(0),
+ category.getHeader() });
+ }
+ }
+ request.setAttribute("categories", categories);
request.setAttribute("id", requestedId);
request.setAttribute("title", this.titles.get(requestedId));
if (this.categories.containsKey(requestedId)) {
diff --git a/website/src/org/torproject/metrics/web/IndexServlet.java b/website/src/org/torproject/metrics/web/IndexServlet.java
index f365cbb..be4134b 100644
--- a/website/src/org/torproject/metrics/web/IndexServlet.java
+++ b/website/src/org/torproject/metrics/web/IndexServlet.java
@@ -4,6 +4,8 @@
package org.torproject.metrics.web;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
@@ -14,11 +16,26 @@ public class IndexServlet extends HttpServlet {
private static final long serialVersionUID = -5156539049907533057L;
+ protected List<String[]> categories;
+
+ @Override
+ public void init() throws ServletException {
+ List<String[]> categories = new ArrayList<String[]>();
+ for (Category category :
+ ContentProvider.getInstance().getCategoriesList()) {
+ categories.add(new String[] {
+ category.getMetrics().isEmpty() ? "" : category.getMetrics().get(0),
+ category.getHeader(), category.getDescription() });
+ }
+ this.categories = categories;
+ }
+
@Override
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
/* Forward the request to the JSP that does all the hard work. */
+ request.setAttribute("categories", this.categories);
request.getRequestDispatcher("WEB-INF/index.jsp").forward(request,
response);
}
diff --git a/website/web/WEB-INF/about.jsp b/website/web/WEB-INF/about.jsp
index a067674..c169969 100644
--- a/website/web/WEB-INF/about.jsp
+++ b/website/web/WEB-INF/about.jsp
@@ -4,6 +4,7 @@
<title>Tor Metrics</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
</head>
<body>
diff --git a/website/web/WEB-INF/bubbles.jsp b/website/web/WEB-INF/bubbles.jsp
index 1fedbeb..9edc575 100644
--- a/website/web/WEB-INF/bubbles.jsp
+++ b/website/web/WEB-INF/bubbles.jsp
@@ -5,6 +5,7 @@
<title>Tor Metrics — Network bubble graphs</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
<script src="js/d3.min.js"></script>
<script src="js/bubbles.js"></script>
diff --git a/website/web/WEB-INF/data.jsp b/website/web/WEB-INF/data.jsp
index d75f4d7..0c86fd7 100644
--- a/website/web/WEB-INF/data.jsp
+++ b/website/web/WEB-INF/data.jsp
@@ -6,6 +6,7 @@
<title>Tor Metrics — ${title}</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
</head>
<body>
diff --git a/website/web/WEB-INF/error.jsp b/website/web/WEB-INF/error.jsp
index 8081f49..0574606 100644
--- a/website/web/WEB-INF/error.jsp
+++ b/website/web/WEB-INF/error.jsp
@@ -6,6 +6,7 @@
<title>Tor Metrics — Error</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
</head>
<body>
diff --git a/website/web/WEB-INF/graph.jsp b/website/web/WEB-INF/graph.jsp
index 2ce9583..aab373a 100644
--- a/website/web/WEB-INF/graph.jsp
+++ b/website/web/WEB-INF/graph.jsp
@@ -6,6 +6,7 @@
<title>Tor Metrics — ${title}</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
</head>
<body>
@@ -30,9 +31,13 @@ of data, rather than just dogma or perspective."
<br>
<!-- Navigation end -->
+<c:forEach var="category" items="${categories}"><c:if test="${fn:length(category[0]) > 0}"><a href="${category[0]}.html"></c:if>${category[1]}<c:if test="${fn:length(category[0]) > 0}"></a></c:if> |
+</c:forEach>
+<br>
+
<h2>${categoryHeader}</h2>
-${categoryDescription}
+<p>${categoryDescription}</p>
<c:forEach var="tab" items="${categoryTabs}">
<c:if test="${fn:length(tab[1]) > 0}"><a href="${tab[1]}.html"></c:if>${tab[0]}<c:if test="${fn:length(tab[1]) > 0}"></a></c:if> |
diff --git a/website/web/WEB-INF/index.jsp b/website/web/WEB-INF/index.jsp
index ad4b79f..2101f5f 100644
--- a/website/web/WEB-INF/index.jsp
+++ b/website/web/WEB-INF/index.jsp
@@ -6,6 +6,7 @@
<title>Tor Metrics</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
</head>
<body>
@@ -33,23 +34,13 @@ of data, rather than just dogma or perspective."
<p>Welcome! What would you like to know about the Tor network?</p>
<div>
-<a href="userstats-relay-country.html"><h3>Users</h3></a>
-<p>Where are Tor users from? How do they connect to Tor?</p>
-<a href="networksize.html"><h3>Relays and Bridges</h3></a>
-<p>How many relays and bridges are online? What do we know about them?</p>
+<c:forEach var="category" items="${categories}">
+<c:if test="${fn:length(category[0]) > 0}"><a href="${category[0]}.html"></c:if><h3>${category[1]}</h3><c:if test="${fn:length(category[0]) > 0}"></a></c:if>
+<p>${category[2]}</p>
+</c:forEach>
+<br>
-<a href="bandwidth.html"><h3>Traffic</h3></a>
-<p>How much traffic can the Tor network handle? How much traffic is there?</p>
-
-<a href="torperf.html"><h3>Performance</h3></a>
-<p>How fast and reliable is the Tor network?</p>
-
-<a href="hidserv-dir-onions-seen.html"><h3>Onion Services</h3></a>
-<p>How many onion services are there? How much traffic do they pull?</p>
-
-<h3>Downloads (coming soon)</h3>
-<p>How many downloads of Tor applications are there? How many updates?</p>
</div>
<p>Let us know if we're missing anything, or if we should measure something
diff --git a/website/web/WEB-INF/link.jsp b/website/web/WEB-INF/link.jsp
index 15a9234..08f7d7b 100644
--- a/website/web/WEB-INF/link.jsp
+++ b/website/web/WEB-INF/link.jsp
@@ -6,6 +6,7 @@
<title>Tor Metrics — ${title}</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
</head>
<body>
diff --git a/website/web/WEB-INF/research.jsp b/website/web/WEB-INF/research.jsp
index 648fdab..52fd50e 100644
--- a/website/web/WEB-INF/research.jsp
+++ b/website/web/WEB-INF/research.jsp
@@ -6,6 +6,7 @@
<title>Tor Metrics</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
</head>
<body>
diff --git a/website/web/WEB-INF/sources.jsp b/website/web/WEB-INF/sources.jsp
index 900bcb2..dc53c52 100644
--- a/website/web/WEB-INF/sources.jsp
+++ b/website/web/WEB-INF/sources.jsp
@@ -6,6 +6,7 @@
<title>Tor Metrics</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
</head>
<body>
diff --git a/website/web/WEB-INF/table.jsp b/website/web/WEB-INF/table.jsp
index ffabd75..eece114 100644
--- a/website/web/WEB-INF/table.jsp
+++ b/website/web/WEB-INF/table.jsp
@@ -6,6 +6,7 @@
<title>Tor Metrics — ${title}</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
</head>
<body>
@@ -32,7 +33,7 @@ of data, rather than just dogma or perspective."
<h2>${categoryHeader}</h2>
-${categoryDescription}
+<p>${categoryDescription}</p>
<c:forEach var="tab" items="${categoryTabs}">
<c:if test="${fn:length(tab[1]) > 0}"><a href="${tab[1]}.html"></c:if>${tab[0]}<c:if test="${fn:length(tab[1]) > 0}"></a></c:if> |
diff --git a/website/web/WEB-INF/tools.jsp b/website/web/WEB-INF/tools.jsp
index f27ece2..d935989 100644
--- a/website/web/WEB-INF/tools.jsp
+++ b/website/web/WEB-INF/tools.jsp
@@ -6,6 +6,7 @@
<title>Tor Metrics</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
</head>
<body>
1
0

09 Jan '17
commit 0140f3e613b8e9f85434a3db04e4e12392ec6980
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Tue Dec 13 21:26:36 2016 +0100
Remove link to About page from footer.
---
website/web/WEB-INF/footer.jsp | 1 -
1 file changed, 1 deletion(-)
diff --git a/website/web/WEB-INF/footer.jsp b/website/web/WEB-INF/footer.jsp
index a4feba7..cab9e7f 100644
--- a/website/web/WEB-INF/footer.jsp
+++ b/website/web/WEB-INF/footer.jsp
@@ -1,4 +1,3 @@
- <p><a href="about.html">About Tor Metrics</a></p>
<p>This material is supported in part by the National Science
Foundation under Grant No. CNS-0959138. Any opinions,
finding, and conclusions or recommendations expressed in this
1
0
commit c7532f18d4f5ac93a7c21fbca3e0274a6c6ac505
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Mon Dec 12 16:40:52 2016 +0100
Put metrics into categories.
---
website/build.xml | 3 +
website/etc/categories.json | 67 ++++++++++++++++++++++
.../src/org/torproject/metrics/web/Category.java | 34 +++++++++++
.../torproject/metrics/web/ContentProvider.java | 38 ++++++++++++
.../org/torproject/metrics/web/GraphServlet.java | 13 +++++
.../org/torproject/metrics/web/MetricServlet.java | 8 +++
.../torproject/metrics/web/MetricsProvider.java | 38 ------------
.../org/torproject/metrics/web/TableServlet.java | 12 ++++
website/web/WEB-INF/graph.jsp | 28 ++++++++-
website/web/WEB-INF/table.jsp | 28 ++++++++-
10 files changed, 229 insertions(+), 40 deletions(-)
diff --git a/website/build.xml b/website/build.xml
index 9f37d13..6e156b4 100644
--- a/website/build.xml
+++ b/website/build.xml
@@ -51,6 +51,9 @@
<zipfileset dir="etc"
prefix="WEB-INF/classes"
includes="metrics.json"/>
+ <zipfileset dir="etc"
+ prefix="WEB-INF/classes"
+ includes="categories.json"/>
<metainf dir="etc"
includes="context.xml"/>
</war>
diff --git a/website/etc/categories.json b/website/etc/categories.json
new file mode 100644
index 0000000..563b662
--- /dev/null
+++ b/website/etc/categories.json
@@ -0,0 +1,67 @@
+[
+ {
+ "id": "clients",
+ "header": "Users",
+ "description": "<p>Where are Tor users from? How do they connect to Tor?</p>",
+ "metrics": [
+ "userstats-relay-country",
+ "userstats-bridge-country",
+ "userstats-bridge-transport",
+ "userstats-bridge-combined",
+ "userstats-bridge-version",
+ "userstats-relay-table",
+ "userstats-censorship-events",
+ "userstats-bridge-table"
+ ]
+ },
+ {
+ "id": "servers",
+ "header": "Relays and Bridges",
+ "description": "<p>How many relays and bridges are online? What do we know about them?</p>",
+ "metrics": [
+ "networksize",
+ "relayflags",
+ "versions",
+ "platforms"
+ ]
+ },
+ {
+ "id": "traffic",
+ "header": "Traffic",
+ "description": "<p>How much traffic can the Tor network handle? How much traffic is there?</p>",
+ "metrics": [
+ "bandwidth",
+ "bandwidth-flags",
+ "advbwdist-perc",
+ "advbwdist-relay",
+ "bwhist-flags",
+ "dirbytes"
+ ]
+ },
+ {
+ "id": "performance",
+ "header": "Performance",
+ "description": "<p>How fast and reliable is the Tor network?</p>",
+ "metrics": [
+ "torperf",
+ "torperf-failures",
+ "connbidirect"
+ ]
+ },
+ {
+ "id": "onion-services",
+ "header": "Onion Services",
+ "description": "<p>How many onion services are there? How much traffic do they pull?</p>",
+ "metrics": [
+ "hidserv-dir-onions-seen",
+ "hidserv-rend-relayed-cells",
+ "hidserv-frac-reporting"
+ ]
+ },
+ {
+ "id": "downloads",
+ "header": "Downloads (coming soon)",
+ "description": "<p>How many downloads of Tor applications are there? How many updates?</p>",
+ "metrics": []
+ }
+]
diff --git a/website/src/org/torproject/metrics/web/Category.java b/website/src/org/torproject/metrics/web/Category.java
new file mode 100644
index 0000000..7f71b22
--- /dev/null
+++ b/website/src/org/torproject/metrics/web/Category.java
@@ -0,0 +1,34 @@
+/* Copyright 2016 The Tor Project
+ * See LICENSE for licensing information */
+
+package org.torproject.metrics.web;
+
+import java.util.List;
+
+public class Category {
+
+ private String id;
+
+ private String header;
+
+ private String description;
+
+ private List<String> metrics;
+
+ public String getId() {
+ return id;
+ }
+
+ public String getHeader() {
+ return header;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public List<String> getMetrics() {
+ return metrics;
+ }
+}
+
diff --git a/website/src/org/torproject/metrics/web/ContentProvider.java b/website/src/org/torproject/metrics/web/ContentProvider.java
new file mode 100644
index 0000000..606e7db
--- /dev/null
+++ b/website/src/org/torproject/metrics/web/ContentProvider.java
@@ -0,0 +1,38 @@
+/* Copyright 2016 The Tor Project
+ * See LICENSE for licensing information */
+
+package org.torproject.metrics.web;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class MetricsProvider {
+
+ private static MetricsProvider instance = new MetricsProvider();
+
+ public static MetricsProvider getInstance() {
+ return MetricsProvider.instance;
+ }
+
+ private List<Metric> metricsList;
+
+ private MetricsProvider() {
+ InputStream in = this.getClass().getClassLoader()
+ .getResourceAsStream("metrics.json");
+ Gson gson = new GsonBuilder().create();
+ Metric[] metricsArray = gson.fromJson(new InputStreamReader(in),
+ Metric[].class);
+ this.metricsList = Arrays.asList(metricsArray);
+ }
+
+ public List<Metric> getMetricsList() {
+ return new ArrayList<Metric>(this.metricsList);
+ }
+}
+
diff --git a/website/src/org/torproject/metrics/web/GraphServlet.java b/website/src/org/torproject/metrics/web/GraphServlet.java
index 189406c..3a73fa5 100644
--- a/website/src/org/torproject/metrics/web/GraphServlet.java
+++ b/website/src/org/torproject/metrics/web/GraphServlet.java
@@ -8,6 +8,7 @@ import org.torproject.metrics.web.graphs.GraphParameterChecker;
import java.io.IOException;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
@@ -135,6 +136,18 @@ public class GraphServlet extends MetricServlet {
}
request.setAttribute("id", requestedId);
request.setAttribute("title", this.titles.get(requestedId));
+ if (this.categories.containsKey(requestedId)) {
+ Category category = this.categories.get(requestedId);
+ request.setAttribute("categoryHeader", category.getHeader());
+ request.setAttribute("categoryDescription", category.getDescription());
+ List<String[]> categoryTabs = new ArrayList<String[]>();
+ for (String metricId : category.getMetrics()) {
+ categoryTabs.add(new String[] {
+ this.titles.get(metricId),
+ requestedId.equals(metricId) ? null : metricId });
+ }
+ request.setAttribute("categoryTabs", categoryTabs);
+ }
request.setAttribute("description",
this.descriptions.get(requestedId));
request.setAttribute("data", this.data.get(requestedId));
diff --git a/website/src/org/torproject/metrics/web/MetricServlet.java b/website/src/org/torproject/metrics/web/MetricServlet.java
index 086f9e7..8de6922 100644
--- a/website/src/org/torproject/metrics/web/MetricServlet.java
+++ b/website/src/org/torproject/metrics/web/MetricServlet.java
@@ -47,6 +47,8 @@ public abstract class MetricServlet extends HttpServlet {
protected Map<String, List<String[]>> related =
new HashMap<String, List<String[]>>();
+ protected Map<String, Category> categories = new HashMap<String, Category>();
+
@Override
public void init() throws ServletException {
this.metrics = MetricsProvider.getInstance().getMetricsList();
@@ -113,6 +115,12 @@ public abstract class MetricServlet extends HttpServlet {
}
}
}
+ for (Category category :
+ CategoriesProvider.getInstance().getCategoriesList()) {
+ for (String id : category.getMetrics()) {
+ categories.put(id, category);
+ }
+ }
}
}
diff --git a/website/src/org/torproject/metrics/web/MetricsProvider.java b/website/src/org/torproject/metrics/web/MetricsProvider.java
deleted file mode 100644
index 606e7db..0000000
--- a/website/src/org/torproject/metrics/web/MetricsProvider.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright 2016 The Tor Project
- * See LICENSE for licensing information */
-
-package org.torproject.metrics.web;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class MetricsProvider {
-
- private static MetricsProvider instance = new MetricsProvider();
-
- public static MetricsProvider getInstance() {
- return MetricsProvider.instance;
- }
-
- private List<Metric> metricsList;
-
- private MetricsProvider() {
- InputStream in = this.getClass().getClassLoader()
- .getResourceAsStream("metrics.json");
- Gson gson = new GsonBuilder().create();
- Metric[] metricsArray = gson.fromJson(new InputStreamReader(in),
- Metric[].class);
- this.metricsList = Arrays.asList(metricsArray);
- }
-
- public List<Metric> getMetricsList() {
- return new ArrayList<Metric>(this.metricsList);
- }
-}
-
diff --git a/website/src/org/torproject/metrics/web/TableServlet.java b/website/src/org/torproject/metrics/web/TableServlet.java
index ad2b10a..035c0be 100644
--- a/website/src/org/torproject/metrics/web/TableServlet.java
+++ b/website/src/org/torproject/metrics/web/TableServlet.java
@@ -50,6 +50,18 @@ public class TableServlet extends MetricServlet {
}
request.setAttribute("id", requestedId);
request.setAttribute("title", this.titles.get(requestedId));
+ if (this.categories.containsKey(requestedId)) {
+ Category category = this.categories.get(requestedId);
+ request.setAttribute("categoryHeader", category.getHeader());
+ request.setAttribute("categoryDescription", category.getDescription());
+ List<String[]> categoryTabs = new ArrayList<String[]>();
+ for (String metricId : category.getMetrics()) {
+ categoryTabs.add(new String[] {
+ this.titles.get(metricId),
+ requestedId.equals(metricId) ? null : metricId });
+ }
+ request.setAttribute("categoryTabs", categoryTabs);
+ }
request.setAttribute("description",
this.descriptions.get(requestedId));
request.setAttribute("tableheader",
diff --git a/website/web/WEB-INF/graph.jsp b/website/web/WEB-INF/graph.jsp
index ad33e4d..2ce9583 100644
--- a/website/web/WEB-INF/graph.jsp
+++ b/website/web/WEB-INF/graph.jsp
@@ -11,8 +11,34 @@
<body>
<div class="center">
<div class="main-column">
+ <h2><a href="/"><img src="images/metrics-logo.png" width="153" height="200" alt="Metrics logo"><img src="images/metrics-wordmark.png" width="384" height="50" alt="Metrics wordmark"></a></h2>
+ <br>
+
+<p>"Tor metrics are the ammunition that lets Tor and other security
+advocates argue for a more private and secure Internet from a position
+of data, rather than just dogma or perspective."
+<i>- Bruce Schneier (June 1, 2016)</i></p>
+
+ <!-- Navigation start -->
+ Metrics |
+ <a href="about.html">About</a> |
+ <a href="news.html">News</a> |
+ <a href="sources.html">Sources</a> |
+ <a href="tools.html">Tools</a> |
+ <a href="research.html">Research</a>
+ <br>
+ <br>
+ <!-- Navigation end -->
+
+<h2>${categoryHeader}</h2>
+
+${categoryDescription}
+
+<c:forEach var="tab" items="${categoryTabs}">
+<c:if test="${fn:length(tab[1]) > 0}"><a href="${tab[1]}.html"></c:if>${tab[0]}<c:if test="${fn:length(tab[1]) > 0}"></a></c:if> |
+</c:forEach>
+<br>
-<h2><a href="."><img src="images/metrics-wordmark-small.png" width="138" height="18" alt="Metrics wordmark"></a> — ${title}</h2>
<br>
${description}
<img src="${id}.png${parameters}"
diff --git a/website/web/WEB-INF/table.jsp b/website/web/WEB-INF/table.jsp
index 1eca70f..ffabd75 100644
--- a/website/web/WEB-INF/table.jsp
+++ b/website/web/WEB-INF/table.jsp
@@ -11,8 +11,34 @@
<body>
<div class="center">
<div class="main-column">
+ <h2><a href="/"><img src="images/metrics-logo.png" width="153" height="200" alt="Metrics logo"><img src="images/metrics-wordmark.png" width="384" height="50" alt="Metrics wordmark"></a></h2>
+ <br>
+
+<p>"Tor metrics are the ammunition that lets Tor and other security
+advocates argue for a more private and secure Internet from a position
+of data, rather than just dogma or perspective."
+<i>- Bruce Schneier (June 1, 2016)</i></p>
+
+ <!-- Navigation start -->
+ Metrics |
+ <a href="about.html">About</a> |
+ <a href="news.html">News</a> |
+ <a href="sources.html">Sources</a> |
+ <a href="tools.html">Tools</a> |
+ <a href="research.html">Research</a>
+ <br>
+ <br>
+ <!-- Navigation end -->
+
+<h2>${categoryHeader}</h2>
+
+${categoryDescription}
+
+<c:forEach var="tab" items="${categoryTabs}">
+<c:if test="${fn:length(tab[1]) > 0}"><a href="${tab[1]}.html"></c:if>${tab[0]}<c:if test="${fn:length(tab[1]) > 0}"></a></c:if> |
+</c:forEach>
+<br>
-<h2><a href="."><img src="images/metrics-wordmark-small.png" width="138" height="18" alt="Metrics wordmark"></a> — ${title}</h2>
<br>
${description}
<form action="${id}.html">
1
0

09 Jan '17
commit b7233e0a6645f26ba227005159fd0ebe3ccd8423
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Mon Dec 12 11:47:43 2016 +0100
Add pages for News, Sources, etc.
---
website/etc/web.xml | 44 ++++++++++++++++++++++
.../org/torproject/metrics/web/NewsServlet.java | 26 +++++++++++++
.../torproject/metrics/web/ResearchServlet.java | 26 +++++++++++++
.../org/torproject/metrics/web/SourcesServlet.java | 26 +++++++++++++
.../org/torproject/metrics/web/ToolsServlet.java | 26 +++++++++++++
website/web/WEB-INF/about.jsp | 27 +++++++++++--
website/web/WEB-INF/index.jsp | 23 ++++++++---
website/web/WEB-INF/news.jsp | 43 +++++++++++++++++++++
website/web/WEB-INF/research.jsp | 43 +++++++++++++++++++++
website/web/WEB-INF/sources.jsp | 43 +++++++++++++++++++++
website/web/WEB-INF/tools.jsp | 43 +++++++++++++++++++++
11 files changed, 362 insertions(+), 8 deletions(-)
diff --git a/website/etc/web.xml b/website/etc/web.xml
index 97400b7..17f6901 100644
--- a/website/etc/web.xml
+++ b/website/etc/web.xml
@@ -209,6 +209,50 @@
<url-pattern>/about.html</url-pattern>
</servlet-mapping>
+ <servlet>
+ <servlet-name>NewsServlet</servlet-name>
+ <servlet-class>
+ org.torproject.metrics.web.NewsServlet
+ </servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>NewsServlet</servlet-name>
+ <url-pattern>/news.html</url-pattern>
+ </servlet-mapping>
+
+ <servlet>
+ <servlet-name>SourcesServlet</servlet-name>
+ <servlet-class>
+ org.torproject.metrics.web.SourcesServlet
+ </servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>SourcesServlet</servlet-name>
+ <url-pattern>/sources.html</url-pattern>
+ </servlet-mapping>
+
+ <servlet>
+ <servlet-name>ToolsServlet</servlet-name>
+ <servlet-class>
+ org.torproject.metrics.web.ToolsServlet
+ </servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>ToolsServlet</servlet-name>
+ <url-pattern>/tools.html</url-pattern>
+ </servlet-mapping>
+
+ <servlet>
+ <servlet-name>ResearchServlet</servlet-name>
+ <servlet-class>
+ org.torproject.metrics.web.ResearchServlet
+ </servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>ResearchServlet</servlet-name>
+ <url-pattern>/research.html</url-pattern>
+ </servlet-mapping>
+
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
diff --git a/website/src/org/torproject/metrics/web/NewsServlet.java b/website/src/org/torproject/metrics/web/NewsServlet.java
new file mode 100644
index 0000000..5186dc6
--- /dev/null
+++ b/website/src/org/torproject/metrics/web/NewsServlet.java
@@ -0,0 +1,26 @@
+/* Copyright 2016 The Tor Project
+ * See LICENSE for licensing information */
+
+package org.torproject.metrics.web;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class NewsServlet extends HttpServlet {
+
+ private static final long serialVersionUID = -7696996243187241242L;
+
+ @Override
+ public void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws IOException, ServletException {
+
+ /* Forward the request to the JSP that does all the hard work. */
+ request.getRequestDispatcher("WEB-INF/news.jsp").forward(request,
+ response);
+ }
+}
+
diff --git a/website/src/org/torproject/metrics/web/ResearchServlet.java b/website/src/org/torproject/metrics/web/ResearchServlet.java
new file mode 100644
index 0000000..ed415b7
--- /dev/null
+++ b/website/src/org/torproject/metrics/web/ResearchServlet.java
@@ -0,0 +1,26 @@
+/* Copyright 2016 The Tor Project
+ * See LICENSE for licensing information */
+
+package org.torproject.metrics.web;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class ResearchServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 7380914323836427960L;
+
+ @Override
+ public void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws IOException, ServletException {
+
+ /* Forward the request to the JSP that does all the hard work. */
+ request.getRequestDispatcher("WEB-INF/research.jsp").forward(request,
+ response);
+ }
+}
+
diff --git a/website/src/org/torproject/metrics/web/SourcesServlet.java b/website/src/org/torproject/metrics/web/SourcesServlet.java
new file mode 100644
index 0000000..98e37d1
--- /dev/null
+++ b/website/src/org/torproject/metrics/web/SourcesServlet.java
@@ -0,0 +1,26 @@
+/* Copyright 2016 The Tor Project
+ * See LICENSE for licensing information */
+
+package org.torproject.metrics.web;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class SourcesServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 8809159168990390124L;
+
+ @Override
+ public void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws IOException, ServletException {
+
+ /* Forward the request to the JSP that does all the hard work. */
+ request.getRequestDispatcher("WEB-INF/sources.jsp").forward(request,
+ response);
+ }
+}
+
diff --git a/website/src/org/torproject/metrics/web/ToolsServlet.java b/website/src/org/torproject/metrics/web/ToolsServlet.java
new file mode 100644
index 0000000..d538512
--- /dev/null
+++ b/website/src/org/torproject/metrics/web/ToolsServlet.java
@@ -0,0 +1,26 @@
+/* Copyright 2016 The Tor Project
+ * See LICENSE for licensing information */
+
+package org.torproject.metrics.web;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class ToolsServlet extends HttpServlet {
+
+ private static final long serialVersionUID = -7868806710366794044L;
+
+ @Override
+ public void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws IOException, ServletException {
+
+ /* Forward the request to the JSP that does all the hard work. */
+ request.getRequestDispatcher("WEB-INF/tools.jsp").forward(request,
+ response);
+ }
+}
+
diff --git a/website/web/WEB-INF/about.jsp b/website/web/WEB-INF/about.jsp
index d5a6f78..91a696b 100644
--- a/website/web/WEB-INF/about.jsp
+++ b/website/web/WEB-INF/about.jsp
@@ -1,7 +1,7 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
- <title>Tor Metrics — About</title>
+ <title>Tor Metrics</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
@@ -9,8 +9,28 @@
<body>
<div class="center">
<div class="main-column">
-<h2><a href="/"><img src="images/metrics-wordmark-small.png" width="138" height="18" alt="Metrics wordmark"></a> — About</h2>
-<br>
+ <h2><a href="/"><img src="images/metrics-logo.png" width="153"
+height="200" al
+t="Metrics logo"><img src="images/metrics-wordmark.png" width="384" height="50"
+alt="M
+etrics wordmark"></a></h2>
+ <br>
+
+<p>"Tor metrics are the ammunition that lets Tor and other security
+advocates argue for a more private and secure Internet from a position
+of data, rather than just dogma or perspective."
+<i>- Bruce Schneier (June 1, 2016)</i></p>
+
+ <!-- Navigation start -->
+ <a href="index.html">Metrics</a> |
+ About |
+ <a href="news.html">News</a> |
+ <a href="sources.html">Sources</a> |
+ <a href="tools.html">Tools</a> |
+ <a href="research.html">Research</a>
+ <br>
+ <br>
+ <!-- Navigation end -->
<h3>Frequently used terms</h3>
<br>
@@ -280,3 +300,4 @@ Git</a>.
</div>
</body>
</html>
+
diff --git a/website/web/WEB-INF/index.jsp b/website/web/WEB-INF/index.jsp
index 68ea0bd..6e06474 100644
--- a/website/web/WEB-INF/index.jsp
+++ b/website/web/WEB-INF/index.jsp
@@ -13,6 +13,23 @@
<div class="main-column">
<h2><a href="/"><img src="images/metrics-logo.png" width="153" height="200" alt="Metrics logo"><img src="images/metrics-wordmark.png" width="384" height="50" alt="Metrics wordmark"></a></h2>
<br>
+
+<p>"Tor metrics are the ammunition that lets Tor and other security
+advocates argue for a more private and secure Internet from a position
+of data, rather than just dogma or perspective."
+<i>- Bruce Schneier (June 1, 2016)</i></p>
+
+ <!-- Navigation start -->
+ Metrics |
+ <a href="about.html">About</a> |
+ <a href="news.html">News</a> |
+ <a href="sources.html">Sources</a> |
+ <a href="tools.html">Tools</a> |
+ <a href="research.html">Research</a>
+ <br>
+ <br>
+ <!-- Navigation end -->
+
<p>Welcome to Tor Metrics, the primary place to learn interesting
facts about the Tor network, the largest deployed anonymity
network to date.
@@ -22,11 +39,6 @@
<a href="https://www.torproject.org/about/contact.html.en">let us
know</a>.</small></p>
-<p>"Tor metrics are the ammunition that lets Tor and other security
-advocates argue for a more private and secure Internet from a position
-of data, rather than just dogma or perspective."
-<i>- Bruce Schneier (June 1, 2016)</i></p>
-
<div>
<div style="border:1px solid gray;border-radius:10px;padding:10px;float:left;overflow:hidden;margin-right:20px;">
<form action="/">
@@ -96,3 +108,4 @@ table {
</div>
</body>
</html>
+
diff --git a/website/web/WEB-INF/news.jsp b/website/web/WEB-INF/news.jsp
new file mode 100644
index 0000000..c47c1b8
--- /dev/null
+++ b/website/web/WEB-INF/news.jsp
@@ -0,0 +1,43 @@
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <title>Tor Metrics</title>
+ <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
+ <link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
+</head>
+<body>
+ <div class="center">
+ <div class="main-column">
+ <h2><a href="/"><img src="images/metrics-logo.png" width="153" height="200" alt="Metrics logo"><img src="images/metrics-wordmark.png" width="384" height="50" alt="Metrics wordmark"></a></h2>
+ <br>
+
+<p>"Tor metrics are the ammunition that lets Tor and other security
+advocates argue for a more private and secure Internet from a position
+of data, rather than just dogma or perspective."
+<i>- Bruce Schneier (June 1, 2016)</i></p>
+
+ <!-- Navigation start -->
+ <a href="index.html">Metrics</a> |
+ <a href="about.html">About</a> |
+ News |
+ <a href="sources.html">Sources</a> |
+ <a href="tools.html">Tools</a> |
+ <a href="research.html">Research</a>
+ <br>
+ <br>
+ <!-- Navigation end -->
+
+<h3>News</h3>
+<br>
+
+ </div>
+ </div>
+ <div class="bottom" id="bottom">
+ <%@ include file="footer.jsp"%>
+ </div>
+</body>
+</html>
+
diff --git a/website/web/WEB-INF/research.jsp b/website/web/WEB-INF/research.jsp
new file mode 100644
index 0000000..648fdab
--- /dev/null
+++ b/website/web/WEB-INF/research.jsp
@@ -0,0 +1,43 @@
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <title>Tor Metrics</title>
+ <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
+ <link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
+</head>
+<body>
+ <div class="center">
+ <div class="main-column">
+ <h2><a href="/"><img src="images/metrics-logo.png" width="153" height="200" alt="Metrics logo"><img src="images/metrics-wordmark.png" width="384" height="50" alt="Metrics wordmark"></a></h2>
+ <br>
+
+<p>"Tor metrics are the ammunition that lets Tor and other security
+advocates argue for a more private and secure Internet from a position
+of data, rather than just dogma or perspective."
+<i>- Bruce Schneier (June 1, 2016)</i></p>
+
+ <!-- Navigation start -->
+ <a href="index.html">Metrics</a> |
+ <a href="about.html">About</a> |
+ <a href="news.html">News</a> |
+ <a href="sources.html">Sources</a> |
+ <a href="tools.html">Tools</a> |
+ Research
+ <br>
+ <br>
+ <!-- Navigation end -->
+
+<h3>Research</h3>
+<br>
+
+ </div>
+ </div>
+ <div class="bottom" id="bottom">
+ <%@ include file="footer.jsp"%>
+ </div>
+</body>
+</html>
+
diff --git a/website/web/WEB-INF/sources.jsp b/website/web/WEB-INF/sources.jsp
new file mode 100644
index 0000000..900bcb2
--- /dev/null
+++ b/website/web/WEB-INF/sources.jsp
@@ -0,0 +1,43 @@
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <title>Tor Metrics</title>
+ <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
+ <link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
+</head>
+<body>
+ <div class="center">
+ <div class="main-column">
+ <h2><a href="/"><img src="images/metrics-logo.png" width="153" height="200" alt="Metrics logo"><img src="images/metrics-wordmark.png" width="384" height="50" alt="Metrics wordmark"></a></h2>
+ <br>
+
+<p>"Tor metrics are the ammunition that lets Tor and other security
+advocates argue for a more private and secure Internet from a position
+of data, rather than just dogma or perspective."
+<i>- Bruce Schneier (June 1, 2016)</i></p>
+
+ <!-- Navigation start -->
+ <a href="index.html">Metrics</a> |
+ <a href="about.html">About</a> |
+ <a href="news.html">News</a> |
+ Sources |
+ <a href="tools.html">Tools</a> |
+ <a href="research.html">Research</a>
+ <br>
+ <br>
+ <!-- Navigation end -->
+
+<h3>Sources</h3>
+<br>
+
+ </div>
+ </div>
+ <div class="bottom" id="bottom">
+ <%@ include file="footer.jsp"%>
+ </div>
+</body>
+</html>
+
diff --git a/website/web/WEB-INF/tools.jsp b/website/web/WEB-INF/tools.jsp
new file mode 100644
index 0000000..f27ece2
--- /dev/null
+++ b/website/web/WEB-INF/tools.jsp
@@ -0,0 +1,43 @@
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <title>Tor Metrics</title>
+ <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
+ <link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
+</head>
+<body>
+ <div class="center">
+ <div class="main-column">
+ <h2><a href="/"><img src="images/metrics-logo.png" width="153" height="200" alt="Metrics logo"><img src="images/metrics-wordmark.png" width="384" height="50" alt="Metrics wordmark"></a></h2>
+ <br>
+
+<p>"Tor metrics are the ammunition that lets Tor and other security
+advocates argue for a more private and secure Internet from a position
+of data, rather than just dogma or perspective."
+<i>- Bruce Schneier (June 1, 2016)</i></p>
+
+ <!-- Navigation start -->
+ <a href="index.html">Metrics</a> |
+ <a href="about.html">About</a> |
+ <a href="news.html">News</a> |
+ <a href="sources.html">Sources</a> |
+ Tools |
+ <a href="research.html">Research</a>
+ <br>
+ <br>
+ <!-- Navigation end -->
+
+<h3>Tools</h3>
+<br>
+
+ </div>
+ </div>
+ <div class="bottom" id="bottom">
+ <%@ include file="footer.jsp"%>
+ </div>
+</body>
+</html>
+
1
0

09 Jan '17
commit 182d61448b7f6ba32b3cccc68d3a0ecda45fea94
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Tue Dec 13 14:03:22 2016 +0100
Add news from a news.json file.
---
website/build.xml | 3 +
website/etc/news.json | 398 +++++++++++++++++++++
.../torproject/metrics/web/ContentProvider.java | 37 +-
.../org/torproject/metrics/web/MetricServlet.java | 4 +-
website/src/org/torproject/metrics/web/News.java | 44 +++
.../org/torproject/metrics/web/NewsServlet.java | 98 ++++-
.../metrics/web/graphs/GraphParameterChecker.java | 4 +-
.../metrics/web/graphs/RObjectGenerator.java | 4 +-
.../metrics/web/graphs/TableParameterChecker.java | 4 +-
website/web/WEB-INF/news.jsp | 7 +
10 files changed, 583 insertions(+), 20 deletions(-)
diff --git a/website/build.xml b/website/build.xml
index 6e156b4..c3aca68 100644
--- a/website/build.xml
+++ b/website/build.xml
@@ -54,6 +54,9 @@
<zipfileset dir="etc"
prefix="WEB-INF/classes"
includes="categories.json"/>
+ <zipfileset dir="etc"
+ prefix="WEB-INF/classes"
+ includes="news.json"/>
<metainf dir="etc"
includes="context.xml"/>
</war>
diff --git a/website/etc/news.json b/website/etc/news.json
new file mode 100644
index 0000000..66db558
--- /dev/null
+++ b/website/etc/news.json
@@ -0,0 +1,398 @@
+[
+ {
+ "start": "2012-05-15",
+ "end": "2012-12-15",
+ "place": "et",
+ "protocols": [
+ "<OR>"
+ ],
+ "description": "Ethiopia blocks Tor TLS.",
+ "links": [
+ "<a href=\"https://bugs.torproject.org/6045\">ticket</a>",
+ "<a href=\"https://blog.torproject.org/blog/ethiopia-introduces-deep-packet-inspection\">blog post 1</a>",
+ "<a href=\"https://blog.torproject.org/blog/update-censorship-ethiopia\">blog post 2</a>"
+ ]
+ },
+ {
+ "start": "2013-08-19",
+ "end": "2014-04-28",
+ "protocols": [
+ "<OR>",
+ "relay"
+ ],
+ "description": "Relay users increase globally from about 800K to over 5M, when computers in the [https://en.wikipedia.org/wiki/Mevade_Botnet Mevade/Sefnit botnetbegan using Tor to communicate. The user count decreased in the following months through efforts to clean up the botnet. Sometime in 2014-04, the botnet switched from using Tor to using SSH.",
+ "links": [
+ "<a href=\"https://blog.torproject.org/blog/how-to-handle-millions-new-tor-clients\">blog post</a>",
+ "<a href=\"https://research.torproject.org/techreports/botnet-tr-2013-11-20.pdf\">tech report</a>",
+ "<a href=\"https://blog.fox-it.com/2013/09/05/large-botnet-cause-of-recent-tor-network…">analysis</a>",
+ "<a href=\"https://www.facebook.com/notes/protect-the-graph/sefnit-is-back/14480871020…">switch to SSH</a>"
+ ]
+ },
+ {
+ "start": "2013-10-27",
+ "protocols": [
+ "<OR>",
+ "relay"
+ ],
+ "description": "Microsoft adds the Mevade/Sefnit botnet signature to various security scanners.",
+ "links": [
+ "<a href=\"https://blogs.technet.microsoft.com/mmpc/2014/01/09/tackling-the-sefnit-bot…">blog post</a>"
+ ]
+ },
+ {
+ "start": "2013-11-03",
+ "protocols": [
+ "<OR>",
+ "relay"
+ ],
+ "description": "Microsoft adds the Mevade/Sefnit botnet signature to their Malicious Software Removal Tool.",
+ "links": [
+ "<a href=\"https://blogs.technet.microsoft.com/mmpc/2014/01/09/tackling-the-sefnit-bot…">blog post</a>"
+ ]
+ },
+ {
+ "start": "2015-11-18",
+ "end": "2015-12-10",
+ "place": "bd",
+ "protocols": [
+ "<OR>",
+ "obfs3",
+ "obfs4"
+ ],
+ "description": "Bangladesh blocks Facebook, WhatsApp, and Viber.",
+ "links": [
+ "<a href=\"http://phys.org/news/2015-12-bangladesh-facebook.html\">news article</a>",
+ "<a href=\"https://archive.fo/fc2WQ\">(archive)</a>",
+ "<a href=\"https://metrics.torproject.org/userstats-relay-country.html?start=2015-08-0…">relay graph</a>"
+ ]
+ },
+ {
+ "start": "2016-04-28",
+ "protocols": [
+ "fte"
+ ],
+ "description": "Tor Browser 6.0a5 and 6.0a5-hardened released, which lack the fte pluggable transport on Mac.",
+ "links": [
+ "<a href=\"https://blog.torproject.org/blog/tor-browser-60a5-released\">6.0a5 blog post</a>",
+ "<a href=\"https://blog.torproject.org/blog/tor-browser-60a5-hardened-released\">6.0a5 blog post</a>",
+ "<a href=\"https://bugs.torproject.org/18495\">ticket</a>"
+ ]
+ },
+ {
+ "start": "2016-05-30",
+ "protocols": [
+ "fte"
+ ],
+ "description": "Tor Browser 6.0 released, which lacks the fte pluggable transport on Mac.",
+ "links": [
+ "<a href=\"https://blog.torproject.org/blog/tor-browser-60-released\">6.0 blog post</a>",
+ "<a href=\"https://bugs.torproject.org/18495\">ticket</a>"
+ ]
+ },
+ {
+ "start": "2016-05-02",
+ "end": "2016-05-03",
+ "place": "br",
+ "protocols": [
+ "<OR>"
+ ],
+ "description": "WhatsApp block in Brazil",
+ "links": [
+ "<a href=\"https://blog.torproject.org/blog/tracking-impact-whatsapp-blockage-tor\">blog post</a>",
+ "<a href=\"https://ooni.torproject.org/post/brazil-whatsapp-block/\">OONI report</a>",
+ "<a href=\"http://bloqueios.info/en/casos/block-for-non-compliance-with-judicial-reque…">bloqueios report</a>"
+ ]
+ },
+ {
+ "start": "2016-06-01",
+ "place": "kz",
+ "protocols": [
+ "<OR>"
+ ],
+ "description": "Kazakhstan blocks vanilla Tor TLS. Users mostly switch to obfs4.",
+ "links": [
+ "<a href=\"https://bugs.torproject.org/20348\">ticket</a>"
+ ]
+ },
+ {
+ "start": "2016-08-20",
+ "place": "ir",
+ "protocols": [
+ "<OR>"
+ ],
+ "description": "Iran somehow blocks most direct Tor connections. May also affect bridge users, but it's hard to tell because there were few vanilla bridge users anyway.",
+ "links": [
+ "<a href=\"https://bugs.torproject.org/20216\">ticket</a>"
+ ]
+ },
+ {
+ "start": "2016-08-24",
+ "protocols": [
+ "bridge"
+ ],
+ "description": "tor 0.2.8.7 and 0.2.9.2-alpha are released, changing the bridge authority from Tonga to Bifroest.",
+ "links": [
+ "<a href=\"https://blog.torproject.org/blog/tor-0287-released-important-fixes\">0.2.8.7 announcement</a>"
+ ]
+ },
+ {
+ "start": "2016-08-31",
+ "protocols": [
+ "bridge"
+ ],
+ "description": "CollecTor begins publishing bridge stats from the new bridge authority Bifroest.",
+ "links": [
+ "<a href=\"https://lists.torproject.org/pipermail/tor-dev/2016-August/011336.html\">post</a>"
+ ]
+ },
+ {
+ "start": "2016-09-02",
+ "protocols": [
+ "bridge"
+ ],
+ "description": "The former bridge authority Tonga shuts down. Bridges that have not updated to tor 0.2.8.7 or 0.2.9.2-alpha (which include all 5 default obfs3 bridges and 3/16 default obfs4 bridges) stop reporting statistics.",
+ "links": [
+ "<a href=\"https://trac.torproject.org/projects/tor/ticket/19690#comment:17\">shutdown notice</a>",
+ "<a href=\"https://blog.torproject.org/blog/new-bridge-authority\">blog post</a>",
+ "<a href=\"https://metrics.torproject.org/networksize.html?start=2016-07-01&end=2016-0…">loss of reporting bridges</a>"
+ ]
+ },
+ {
+ "start": "2016-09-04",
+ "place": "ir",
+ "protocols": [
+ "<OR>"
+ ],
+ "description": "Iran intensifies the blocking begun on 2016-08-20, getting most of the remaining direct users. There is interference in the graphs from the bridge authority changeover on 2016-09-02, but because the changeover would not have affected counts of ''direct'' users, it may be a coincidence.",
+ "links": [
+ "<a href=\"https://bugs.torproject.org/20216\">ticket</a>"
+ ]
+ },
+ {
+ "start": "2016-09-20",
+ "protocols": [
+ "meek"
+ ],
+ "description": "macOS 10.12 (Sierra) is released, breaking some programs that are built with Go <1.7, including the meek-client that comes with Tor Browser. (See 2016-11-15 unbreaking event.)",
+ "links": [
+ "<a href=\"https://bugs.torproject.org/20250\">ticket</a>"
+ ]
+ },
+ {
+ "start": "2016-09-23",
+ "protocols": [
+ "obfs3"
+ ],
+ "description": "Default obfs3 bridges ndnop0 and ndnop2 upgrade and begin reporting statistics to the new bridge authority Bifroest.",
+ "links": [
+ "<a href=\"https://lists.torproject.org/pipermail/metrics-team/2016-September/000217.h…">post on bridges not reporting statistics</a>"
+ ]
+ },
+ {
+ "start": "2016-09-23",
+ "protocols": [
+ "obfs4"
+ ],
+ "description": "Default obfs3 bridges ndnop3 and ndnop5 upgrade and begin reporting statistics to the new bridge authority Bifroest.",
+ "links": [
+ "<a href=\"https://lists.torproject.org/pipermail/metrics-team/2016-September/000217.h…">post on bridges not reporting statistics</a>"
+ ]
+ },
+ {
+ "start": "2016-09-23",
+ "protocols": [
+ "obfs3"
+ ],
+ "description": "Default obfs3 bridges \"Unnamed\" and \"Unnamed\" (fingerprint <a href=\"https://atlas.torproject.org/#details/AF9F66B7B04F8FF6F32D455F05135250A1654…">AF9F66B7B04F8FF6F32D455F05135250A16543C9</a>) upgrade and begin reporting statistics to the new bridge authority Bifroest.",
+ "links": []
+ },
+ {
+ "start": "2016-09-24",
+ "protocols": [
+ "obfs3"
+ ],
+ "description": "Default obfs3 bridge LeifEricson upgrades and begins reporting statistics to the new bridge authority Bifroest. This is the last obfs3 bridge that hadn't upgraded.",
+ "links": []
+ },
+ {
+ "start": "2016-09-24",
+ "protocols": [
+ "obfs4"
+ ],
+ "description": "Default obfs4 bridge LeifEricson upgrades and begins reporting statistics to the new bridge authority Bifroest. This is the last obfs4 bridge that hadn't upgraded.",
+ "links": []
+ },
+ {
+ "start": "2016-10-02",
+ "end": "2016-10-03",
+ "place": "eg",
+ "protocols": [
+ "<OR>",
+ "relay"
+ ],
+ "description": "Reports that direct connections from Egypt are blocked; bridges are required. Maybe be the same as the block beginning 2016-10-25.",
+ "links": [
+ "<a href=\"https://ooni.torproject.org/post/egypt-network-interference/#attempts-to-bl…">OONI report</a>"
+ ]
+ },
+ {
+ "start": "2016-10-08",
+ "end": "2016-10-09",
+ "place": "tr",
+ "description": "Turkey blocks storage services including Dropbox, Google Drive, OneDrive, and GitHub. Most (all?) of the blocks were rescinded the next day.",
+ "links": [
+ "<a href=\"https://turkeyblocks.org/2016/10/08/google-drive-dropbox-blocked-in-turkey/\">blocking article</a>",
+ "<a href=\"https://twitter.com/TurkeyBlocks/status/785054084856512512\">unblocking tweet</a>",
+ "<a href=\"https://www.turkishminute.com/2016/10/09/turkey-lifts-block-dropbox-google-…">unblocking article</a>"
+ ]
+ },
+ {
+ "start": "2016-10-19",
+ "end": "2016-11-10",
+ "protocols": [
+ "meek"
+ ],
+ "description": "Large decrease in meek users, perhaps caused by problems in Orbot 15.0.2 BETA 1 that were fixed in Orbot 15.2.0 RC8.",
+ "links": [
+ "<a href=\"https://bugs.torproject.org/20495\">ticket</a>",
+ "<a href=\"https://lists.torproject.org/pipermail/tor-project/2016-October/000764.html\">initial email</a>",
+ "<a href=\"https://lists.torproject.org/pipermail/tor-project/2016-November/000778.htm…">followup email</a>",
+ "<a href=\"https://groups.google.com/d/msg/traffic-obf/CSJLt3t-_OI/FnAqWqquAwAJ\">Orbot mail</a>"
+ ]
+ },
+ {
+ "start": "2016-10-25",
+ "place": "eg",
+ "protocols": [
+ "<OR>",
+ "relay"
+ ],
+ "description": "Egypt blocks Tor directory authorities and public relays by TCP RST. Bridges work.",
+ "links": [
+ "<a href=\"https://ooni.torproject.org/post/egypt-network-interference/#attempts-to-bl…">OONI report</a>"
+ ]
+ },
+ {
+ "start": "2016-11-03",
+ "place": "tr",
+ "description": "Turkey blocks Facebook, Twitter, YouTube, WhatsApp",
+ "links": [
+ "<a href=\"https://turkeyblocks.org/2016/11/04/social-media-shutdown-turkey/\">article</a>"
+ ]
+ },
+ {
+ "start": "2016-11-04",
+ "place": "tr",
+ "description": "Turkey orders a block on VPN services and Tor",
+ "links": [
+ "<a href=\"http://turk-internet.com/portal/yazigoster.php?yaziid=54465\">Turkish article</a>",
+ "<a href=\"https://motherboard.vice.com/read/turkey-doubles-down-on-censorship-with-bl…">English article</a>"
+ ]
+ },
+ {
+ "start": "2016-11-15",
+ "protocols": [
+ "meek"
+ ],
+ "description": "Tor Browser 6.0.6 is released, unbreaking meek on macOS 10.12 (Sierra). (See 2016-09-20 breaking event.)",
+ "links": [
+ "<a href=\"https://blog.torproject.org/blog/tor-browser-606-released\">blog post</a>",
+ "<a href=\"https://bugs.torproject.org/20250#comment:29\">ticket</a>"
+ ]
+ },
+ {
+ "start": "2016-11-15",
+ "protocols": [
+ "obfs4"
+ ],
+ "description": "Default obfs4 bridges ndnop3 and ndnop5 turn on timing obfuscation (`iat-mode`).",
+ "links": [
+ "<a href=\"https://lists.torproject.org/pipermail/tor-project/2016-November/000780.htm…">mailing list post</a>",
+ "<a href=\"https://bugs.torproject.org/20837\">ticket</a>"
+ ]
+ },
+ {
+ "start": "2016-11-18",
+ "protocols": [
+ "obfs4"
+ ],
+ "description": "Default obfs4 bridge <a href=\"https://atlas.torproject.org/#details/D9C805C955CB124D188C0D44F271E9BE57DE2…">Lisbeth</a> turns on timing obfuscation (`iat-mode=1`).",
+ "links": [
+ "<a href=\"https://bugs.torproject.org/20837\">ticket</a>"
+ ]
+ },
+ {
+ "start": "2016-09-23",
+ "end": "2016-11-28",
+ "protocols": [
+ "obfs3"
+ ],
+ "description": "Outage of default obfs3 bridges \"Unnamed\" and \"Unnamed\" (fingerprint <a href=\"https://atlas.torproject.org/#details/AF9F66B7B04F8FF6F32D455F05135250A1654…">AF9F66B7B04F8FF6F32D455F05135250A16543C9</a>). (Start date not known for sure, though it must have been after 2016-09-23; discussed in non-archived tor-team email.)",
+ "links": []
+ },
+ {
+ "start": "2016-12-01",
+ "place": "by",
+ "protocols": [
+ "<OR>",
+ "relay"
+ ],
+ "description": "Belarus blocks the addresses of public Tor relays, apparently by RST injection. Bridges work, even unobfuscated ones.",
+ "links": [
+ "<a href=\"https://bugs.torproject.org/20907\">ticket</a>",
+ "<a href=\"https://geektimes.ru/post/283392/\">article (Russian)</a>",
+ "<a href=\"https://ooni.torproject.org/post/belarus-fries-onion/\">OONI blog post</a>"
+ ]
+ },
+ {
+ "start": "2016-02-24",
+ "place": "tm",
+ "protocols": [
+ "<OR>"
+ ],
+ "description": "Large drop in direct users in Turkmenistan",
+ "links": [
+ "<a href=\"https://metrics.torproject.org/userstats-relay-country.html?start=2015-11-0…">graph</a>"
+ ],
+ "unknown": true
+ },
+ {
+ "start": "2016-08-24",
+ "place": "cn",
+ "protocols": [
+ "<OR>"
+ ],
+ "description": "Large decrease in users in China",
+ "links": [
+ "<a href=\"https://metrics.torproject.org/userstats-relay-country.html?start=2016-07-3…">relay</a>",
+ "<a href=\"https://metrics.torproject.org/userstats-bridge-country.html?start=2016-07-…">bridge</a>"
+ ],
+ "unknown": true
+ },
+ {
+ "start": "2016-10-09",
+ "end": "2016-10-25",
+ "place": "il",
+ "protocols": [
+ "<OR>"
+ ],
+ "description": "Direct users fluctuate wildly in Israel. Bridge users not affected.",
+ "links": [
+ "<a href=\"https://metrics.torproject.org/userstats-relay-country.html?start=2016-07-2…">graph</a>"
+ ],
+ "unknown": true
+ },
+ {
+ "start": "2016-11-20",
+ "place": "sa",
+ "protocols": [
+ "<OR>",
+ "relay"
+ ],
+ "description": "Decrease in direct users in Saudi Arabia.",
+ "links": [
+ "<a href=\"https://bugs.torproject.org/20785\">ticket</a>"
+ ],
+ "unknown": true
+ }
+]
diff --git a/website/src/org/torproject/metrics/web/ContentProvider.java b/website/src/org/torproject/metrics/web/ContentProvider.java
index 606e7db..2dd9105 100644
--- a/website/src/org/torproject/metrics/web/ContentProvider.java
+++ b/website/src/org/torproject/metrics/web/ContentProvider.java
@@ -6,33 +6,48 @@ package org.torproject.metrics.web;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
-import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-public class MetricsProvider {
+public class ContentProvider {
- private static MetricsProvider instance = new MetricsProvider();
+ private static ContentProvider instance = new ContentProvider();
- public static MetricsProvider getInstance() {
- return MetricsProvider.instance;
+ public static ContentProvider getInstance() {
+ return ContentProvider.instance;
}
private List<Metric> metricsList;
- private MetricsProvider() {
- InputStream in = this.getClass().getClassLoader()
- .getResourceAsStream("metrics.json");
+ private List<Category> categoriesList;
+
+ private List<News> newsList;
+
+ private ContentProvider() {
Gson gson = new GsonBuilder().create();
- Metric[] metricsArray = gson.fromJson(new InputStreamReader(in),
- Metric[].class);
- this.metricsList = Arrays.asList(metricsArray);
+ this.metricsList = Arrays.asList(gson.fromJson(new InputStreamReader(
+ this.getClass().getClassLoader().getResourceAsStream("metrics.json")),
+ Metric[].class));
+ this.categoriesList = Arrays.asList(gson.fromJson(new InputStreamReader(
+ this.getClass().getClassLoader().getResourceAsStream(
+ "categories.json")), Category[].class));
+ this.newsList = Arrays.asList(gson.fromJson(new InputStreamReader(
+ this.getClass().getClassLoader().getResourceAsStream(
+ "news.json")), News[].class));
}
public List<Metric> getMetricsList() {
return new ArrayList<Metric>(this.metricsList);
}
+
+ public List<Category> getCategoriesList() {
+ return new ArrayList<Category>(this.categoriesList);
+ }
+
+ public List<News> getNewsList() {
+ return new ArrayList<News>(this.newsList);
+ }
}
diff --git a/website/src/org/torproject/metrics/web/MetricServlet.java b/website/src/org/torproject/metrics/web/MetricServlet.java
index 8de6922..a280ee4 100644
--- a/website/src/org/torproject/metrics/web/MetricServlet.java
+++ b/website/src/org/torproject/metrics/web/MetricServlet.java
@@ -51,7 +51,7 @@ public abstract class MetricServlet extends HttpServlet {
@Override
public void init() throws ServletException {
- this.metrics = MetricsProvider.getInstance().getMetricsList();
+ this.metrics = ContentProvider.getInstance().getMetricsList();
Map<String, String> allTypesAndTitles = new HashMap<String, String>();
Map<String, String[]> dataIds = new HashMap<String, String[]>();
Map<String, String[]> relatedIds = new HashMap<String, String[]>();
@@ -116,7 +116,7 @@ public abstract class MetricServlet extends HttpServlet {
}
}
for (Category category :
- CategoriesProvider.getInstance().getCategoriesList()) {
+ ContentProvider.getInstance().getCategoriesList()) {
for (String id : category.getMetrics()) {
categories.put(id, category);
}
diff --git a/website/src/org/torproject/metrics/web/News.java b/website/src/org/torproject/metrics/web/News.java
new file mode 100644
index 0000000..d16c3a1
--- /dev/null
+++ b/website/src/org/torproject/metrics/web/News.java
@@ -0,0 +1,44 @@
+/* Copyright 2016 The Tor Project
+ * See LICENSE for licensing information */
+
+package org.torproject.metrics.web;
+
+public class News {
+
+ private String start;
+
+ private String end;
+
+ private String place;
+
+ private String[] protocols;
+
+ private String description;
+
+ private String[] links;
+
+ String getStart() {
+ return start;
+ }
+
+ String getEnd() {
+ return end;
+ }
+
+ String getPlace() {
+ return place;
+ }
+
+ String[] getProtocols() {
+ return protocols;
+ }
+
+ String getDescription() {
+ return description;
+ }
+
+ String[] getLinks() {
+ return links;
+ }
+}
+
diff --git a/website/src/org/torproject/metrics/web/NewsServlet.java b/website/src/org/torproject/metrics/web/NewsServlet.java
index 5186dc6..f924b67 100644
--- a/website/src/org/torproject/metrics/web/NewsServlet.java
+++ b/website/src/org/torproject/metrics/web/NewsServlet.java
@@ -4,6 +4,18 @@
package org.torproject.metrics.web;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TimeZone;
+import java.util.TreeMap;
+import java.util.TreeSet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
@@ -14,11 +26,95 @@ public class NewsServlet extends HttpServlet {
private static final long serialVersionUID = -7696996243187241242L;
+ protected SortedSet<News> sortedNews;
+
+ @Override
+ public void init() throws ServletException {
+ SortedSet<News> sortedNews = new TreeSet<News>(new Comparator<News>() {
+ public int compare(News o1, News o2) {
+ return o1.getStart().compareTo(o2.getStart()) * -1;
+ }
+ });
+ for (News news : ContentProvider.getInstance().getNewsList()) {
+ if (news.getStart() != null) {
+ sortedNews.add(news);
+ }
+ }
+ this.sortedNews = sortedNews;
+ }
+
@Override
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
- /* Forward the request to the JSP that does all the hard work. */
+ /* Create categories based on current system time. */
+ Map<String, String> cutOffDates = new LinkedHashMap<String, String>();
+ Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US);
+ cal.set(Calendar.DAY_OF_WEEK, 1);
+ cutOffDates.put(String.format("%tF", cal), "This week");
+ cal.set(Calendar.DAY_OF_MONTH, 1);
+ cutOffDates.put(String.format("%tF", cal), "This month");
+ cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) /3 * 3);
+ cutOffDates.put(String.format("%tF", cal), "This quarter");
+ cal.set(Calendar.MONTH, 0);
+ String yearStart = String.format("%tF", cal);
+ cutOffDates.put(yearStart, "This year");
+ do {
+ cal.add(Calendar.YEAR, -1);
+ yearStart = String.format("%tF", cal);
+ cutOffDates.put(yearStart, String.format("%tY", cal));
+ } while (yearStart.compareTo(this.sortedNews.first().getStart()) > 0);
+
+ /* Sort news into categories. */
+ Map<String, List<String[]>> newsByCategory =
+ new LinkedHashMap<String, List<String[]>>();
+ for (String category : cutOffDates.values()) {
+ newsByCategory.put(category, new ArrayList<String[]>());
+ }
+ for (News news : this.sortedNews) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("<p>" + news.getStart());
+ if (news.getEnd() != null) {
+ sb.append("–" + news.getEnd());
+ }
+ sb.append(": ");
+ if (news.getPlace() != null) {
+ sb.append(news.getPlace() + ", ");
+ }
+ if (news.getProtocols() != null) {
+ int written = 0;
+ for (String protocol : news.getProtocols()) {
+ sb.append((written++ > 0 ? ", " : "") + protocol);
+ }
+ }
+ sb.append(", " + news.getDescription());
+ if (news.getLinks() != null && news.getLinks().length > 0) {
+ int written = 0;
+ sb.append(" (");
+ for (String link : news.getLinks()) {
+ sb.append((written++ > 0 ? " " : "") + link);
+ }
+ sb.append(")");
+ }
+ sb.append("</p>");
+ String[] formattedNews = new String[] { sb.toString() };
+ for (Map.Entry<String, String> category : cutOffDates.entrySet()) {
+ if (news.getStart().compareTo(category.getKey()) >= 0) {
+ newsByCategory.get(category.getValue()).add(formattedNews);
+ break;
+ }
+ }
+ }
+
+ /* Remove categories without news. */
+ for (String category : cutOffDates.values()) {
+ if (newsByCategory.get(category).isEmpty()) {
+ newsByCategory.remove(category);
+ }
+ }
+
+ /* Pass news by category to the JSP and let it do the rest of the work. */
+ request.setAttribute("news", newsByCategory);
request.getRequestDispatcher("WEB-INF/news.jsp").forward(request,
response);
}
diff --git a/website/src/org/torproject/metrics/web/graphs/GraphParameterChecker.java b/website/src/org/torproject/metrics/web/graphs/GraphParameterChecker.java
index b40885c..9f2a774 100644
--- a/website/src/org/torproject/metrics/web/graphs/GraphParameterChecker.java
+++ b/website/src/org/torproject/metrics/web/graphs/GraphParameterChecker.java
@@ -3,8 +3,8 @@
package org.torproject.metrics.web.graphs;
+import org.torproject.metrics.web.ContentProvider;
import org.torproject.metrics.web.Metric;
-import org.torproject.metrics.web.MetricsProvider;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -50,7 +50,7 @@ public class GraphParameterChecker {
this.dateFormat = new SimpleDateFormat("yyyy-MM-dd");
this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
this.availableGraphs = new HashMap<String, String[]>();
- for (Metric metric : MetricsProvider.getInstance().getMetricsList()) {
+ for (Metric metric : ContentProvider.getInstance().getMetricsList()) {
if ("Graph".equals(metric.getType())) {
this.availableGraphs.put(metric.getId(), metric.getParameters());
}
diff --git a/website/src/org/torproject/metrics/web/graphs/RObjectGenerator.java b/website/src/org/torproject/metrics/web/graphs/RObjectGenerator.java
index 526e3d3..87f3e33 100644
--- a/website/src/org/torproject/metrics/web/graphs/RObjectGenerator.java
+++ b/website/src/org/torproject/metrics/web/graphs/RObjectGenerator.java
@@ -3,8 +3,8 @@
package org.torproject.metrics.web.graphs;
+import org.torproject.metrics.web.ContentProvider;
import org.torproject.metrics.web.Metric;
-import org.torproject.metrics.web.MetricsProvider;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;
@@ -59,7 +59,7 @@ public class RObjectGenerator implements ServletContextListener {
this.availableGraphs = new LinkedHashMap<String, Metric>();
this.availableTables = new LinkedHashMap<String, Metric>();
- for (Metric metric : MetricsProvider.getInstance().getMetricsList()) {
+ for (Metric metric : ContentProvider.getInstance().getMetricsList()) {
String type = metric.getType();
String id = metric.getId();
if ("Graph".equals(type)) {
diff --git a/website/src/org/torproject/metrics/web/graphs/TableParameterChecker.java b/website/src/org/torproject/metrics/web/graphs/TableParameterChecker.java
index b441ab6..c068b7d 100644
--- a/website/src/org/torproject/metrics/web/graphs/TableParameterChecker.java
+++ b/website/src/org/torproject/metrics/web/graphs/TableParameterChecker.java
@@ -3,8 +3,8 @@
package org.torproject.metrics.web.graphs;
+import org.torproject.metrics.web.ContentProvider;
import org.torproject.metrics.web.Metric;
-import org.torproject.metrics.web.MetricsProvider;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -47,7 +47,7 @@ public class TableParameterChecker {
this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
this.availableTables = new HashMap<String, String[]>();
- for (Metric metric : MetricsProvider.getInstance().getMetricsList()) {
+ for (Metric metric : ContentProvider.getInstance().getMetricsList()) {
if ("Table".equals(metric.getType())) {
this.availableTables.put(metric.getId(), metric.getParameters());
}
diff --git a/website/web/WEB-INF/news.jsp b/website/web/WEB-INF/news.jsp
index c47c1b8..61c81b0 100644
--- a/website/web/WEB-INF/news.jsp
+++ b/website/web/WEB-INF/news.jsp
@@ -33,6 +33,13 @@ of data, rather than just dogma or perspective."
<h3>News</h3>
<br>
+<c:forEach var="category" items="${news}">
+<h3>${category.key}</h3>
+<c:forEach var="entry" items="${category.value}">
+<p>${entry[0]}</p>
+</c:forEach>
+</c:forEach>
+
</div>
</div>
<div class="bottom" id="bottom">
1
0
commit 30fbb7b16c40f8b30c7d3c626755079781e3615e
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Tue Dec 13 15:08:14 2016 +0100
Tweak news.
---
website/etc/news.json | 32 ++++----
website/src/org/torproject/metrics/web/News.java | 18 +++--
.../org/torproject/metrics/web/NewsServlet.java | 87 +++++++++++++++-------
website/web/WEB-INF/news.jsp | 15 +++-
website/web/css/bootstrap.min.css | 6 ++
5 files changed, 110 insertions(+), 48 deletions(-)
diff --git a/website/etc/news.json b/website/etc/news.json
index 66db558..f9df721 100644
--- a/website/etc/news.json
+++ b/website/etc/news.json
@@ -4,7 +4,7 @@
"end": "2012-12-15",
"place": "et",
"protocols": [
- "<OR>"
+ "<OR>"
],
"description": "Ethiopia blocks Tor TLS.",
"links": [
@@ -17,7 +17,7 @@
"start": "2013-08-19",
"end": "2014-04-28",
"protocols": [
- "<OR>",
+ "<OR>",
"relay"
],
"description": "Relay users increase globally from about 800K to over 5M, when computers in the [https://en.wikipedia.org/wiki/Mevade_Botnet Mevade/Sefnit botnetbegan using Tor to communicate. The user count decreased in the following months through efforts to clean up the botnet. Sometime in 2014-04, the botnet switched from using Tor to using SSH.",
@@ -31,7 +31,7 @@
{
"start": "2013-10-27",
"protocols": [
- "<OR>",
+ "<OR>",
"relay"
],
"description": "Microsoft adds the Mevade/Sefnit botnet signature to various security scanners.",
@@ -42,7 +42,7 @@
{
"start": "2013-11-03",
"protocols": [
- "<OR>",
+ "<OR>",
"relay"
],
"description": "Microsoft adds the Mevade/Sefnit botnet signature to their Malicious Software Removal Tool.",
@@ -55,7 +55,7 @@
"end": "2015-12-10",
"place": "bd",
"protocols": [
- "<OR>",
+ "<OR>",
"obfs3",
"obfs4"
],
@@ -94,7 +94,7 @@
"end": "2016-05-03",
"place": "br",
"protocols": [
- "<OR>"
+ "<OR>"
],
"description": "WhatsApp block in Brazil",
"links": [
@@ -107,7 +107,7 @@
"start": "2016-06-01",
"place": "kz",
"protocols": [
- "<OR>"
+ "<OR>"
],
"description": "Kazakhstan blocks vanilla Tor TLS. Users mostly switch to obfs4.",
"links": [
@@ -118,7 +118,7 @@
"start": "2016-08-20",
"place": "ir",
"protocols": [
- "<OR>"
+ "<OR>"
],
"description": "Iran somehow blocks most direct Tor connections. May also affect bridge users, but it's hard to tell because there were few vanilla bridge users anyway.",
"links": [
@@ -161,7 +161,7 @@
"start": "2016-09-04",
"place": "ir",
"protocols": [
- "<OR>"
+ "<OR>"
],
"description": "Iran intensifies the blocking begun on 2016-08-20, getting most of the remaining direct users. There is interference in the graphs from the bridge authority changeover on 2016-09-02, but because the changeover would not have affected counts of ''direct'' users, it may be a coincidence.",
"links": [
@@ -227,7 +227,7 @@
"end": "2016-10-03",
"place": "eg",
"protocols": [
- "<OR>",
+ "<OR>",
"relay"
],
"description": "Reports that direct connections from Egypt are blocked; bridges are required. Maybe be the same as the block beginning 2016-10-25.",
@@ -264,7 +264,7 @@
"start": "2016-10-25",
"place": "eg",
"protocols": [
- "<OR>",
+ "<OR>",
"relay"
],
"description": "Egypt blocks Tor directory authorities and public relays by TCP RST. Bridges work.",
@@ -334,7 +334,7 @@
"start": "2016-12-01",
"place": "by",
"protocols": [
- "<OR>",
+ "<OR>",
"relay"
],
"description": "Belarus blocks the addresses of public Tor relays, apparently by RST injection. Bridges work, even unobfuscated ones.",
@@ -348,7 +348,7 @@
"start": "2016-02-24",
"place": "tm",
"protocols": [
- "<OR>"
+ "<OR>"
],
"description": "Large drop in direct users in Turkmenistan",
"links": [
@@ -360,7 +360,7 @@
"start": "2016-08-24",
"place": "cn",
"protocols": [
- "<OR>"
+ "<OR>"
],
"description": "Large decrease in users in China",
"links": [
@@ -374,7 +374,7 @@
"end": "2016-10-25",
"place": "il",
"protocols": [
- "<OR>"
+ "<OR>"
],
"description": "Direct users fluctuate wildly in Israel. Bridge users not affected.",
"links": [
@@ -386,7 +386,7 @@
"start": "2016-11-20",
"place": "sa",
"protocols": [
- "<OR>",
+ "<OR>",
"relay"
],
"description": "Decrease in direct users in Saudi Arabia.",
diff --git a/website/src/org/torproject/metrics/web/News.java b/website/src/org/torproject/metrics/web/News.java
index d16c3a1..5593b04 100644
--- a/website/src/org/torproject/metrics/web/News.java
+++ b/website/src/org/torproject/metrics/web/News.java
@@ -17,28 +17,34 @@ public class News {
private String[] links;
+ private boolean unknown;
+
String getStart() {
- return start;
+ return this.start;
}
String getEnd() {
- return end;
+ return this.end;
}
String getPlace() {
- return place;
+ return this.place;
}
String[] getProtocols() {
- return protocols;
+ return this.protocols;
}
String getDescription() {
- return description;
+ return this.description;
}
String[] getLinks() {
- return links;
+ return this.links;
+ }
+
+ boolean isUnknown() {
+ return this.unknown;
}
}
diff --git a/website/src/org/torproject/metrics/web/NewsServlet.java b/website/src/org/torproject/metrics/web/NewsServlet.java
index f924b67..2cf4291 100644
--- a/website/src/org/torproject/metrics/web/NewsServlet.java
+++ b/website/src/org/torproject/metrics/web/NewsServlet.java
@@ -3,19 +3,20 @@
package org.torproject.metrics.web;
+import org.torproject.metrics.web.graphs.Countries;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
+import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.SortedMap;
-import java.util.SortedSet;
import java.util.TimeZone;
import java.util.TreeMap;
-import java.util.TreeSet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
@@ -26,21 +27,29 @@ public class NewsServlet extends HttpServlet {
private static final long serialVersionUID = -7696996243187241242L;
- protected SortedSet<News> sortedNews;
+ protected List<News> sortedNews;
+
+ protected SortedMap<String, String> countries;
@Override
public void init() throws ServletException {
- SortedSet<News> sortedNews = new TreeSet<News>(new Comparator<News>() {
- public int compare(News o1, News o2) {
- return o1.getStart().compareTo(o2.getStart()) * -1;
- }
- });
+ List<News> sortedNews = new ArrayList<News>();
for (News news : ContentProvider.getInstance().getNewsList()) {
if (news.getStart() != null) {
sortedNews.add(news);
}
}
+ Collections.sort(sortedNews, new Comparator<News>() {
+ public int compare(News o1, News o2) {
+ return o1.getStart().compareTo(o2.getStart()) * -1;
+ }
+ });
this.sortedNews = sortedNews;
+ SortedMap<String, String> countries = new TreeMap<String, String>();
+ for (String[] country : Countries.getInstance().getCountryList()) {
+ countries.put(country[0], country[1]);
+ }
+ this.countries = countries;
}
@Override
@@ -48,27 +57,33 @@ public class NewsServlet extends HttpServlet {
HttpServletResponse response) throws IOException, ServletException {
/* Create categories based on current system time. */
- Map<String, String> cutOffDates = new LinkedHashMap<String, String>();
+ Map<String, String[]> cutOffDates = new LinkedHashMap<String, String[]>();
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US);
cal.set(Calendar.DAY_OF_WEEK, 1);
- cutOffDates.put(String.format("%tF", cal), "This week");
+ cutOffDates.put(String.format("%tF", cal),
+ new String[] { "This week", "week" });
cal.set(Calendar.DAY_OF_MONTH, 1);
- cutOffDates.put(String.format("%tF", cal), "This month");
+ cutOffDates.put(String.format("%tF", cal),
+ new String[] { "This month", "month" });
cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) /3 * 3);
- cutOffDates.put(String.format("%tF", cal), "This quarter");
+ cutOffDates.put(String.format("%tF", cal),
+ new String[] { "This quarter", "quarter" });
cal.set(Calendar.MONTH, 0);
String yearStart = String.format("%tF", cal);
- cutOffDates.put(yearStart, "This year");
+ cutOffDates.put(yearStart,
+ new String[] { "This year", "year" });
do {
cal.add(Calendar.YEAR, -1);
yearStart = String.format("%tF", cal);
- cutOffDates.put(yearStart, String.format("%tY", cal));
- } while (yearStart.compareTo(this.sortedNews.first().getStart()) > 0);
+ String year = String.format("%tY", cal);
+ cutOffDates.put(yearStart, new String[] { year, year });
+ } while (!this.sortedNews.isEmpty() &&
+ yearStart.compareTo(this.sortedNews.get(0).getStart()) > 0);
/* Sort news into categories. */
- Map<String, List<String[]>> newsByCategory =
- new LinkedHashMap<String, List<String[]>>();
- for (String category : cutOffDates.values()) {
+ Map<String[], List<String[]>> newsByCategory =
+ new LinkedHashMap<String[], List<String[]>>();
+ for (String[] category : cutOffDates.values()) {
newsByCategory.put(category, new ArrayList<String[]>());
}
for (News news : this.sortedNews) {
@@ -77,17 +92,39 @@ public class NewsServlet extends HttpServlet {
if (news.getEnd() != null) {
sb.append("–" + news.getEnd());
}
- sb.append(": ");
if (news.getPlace() != null) {
- sb.append(news.getPlace() + ", ");
+ if (this.countries.containsKey(news.getPlace())) {
+ sb.append(" <span class=\"label label-warning\">"
+ + this.countries.get(news.getPlace()) + "</span>");
+ } else {
+ sb.append(" <span class=\"label label-warning\">"
+ + "Unknown country</span>");
+ }
}
if (news.getProtocols() != null) {
- int written = 0;
for (String protocol : news.getProtocols()) {
- sb.append((written++ > 0 ? ", " : "") + protocol);
+ if (protocol.equals("relay")) {
+ sb.append(" <span class=\"label label-success\">"
+ + "Relays</span>");
+ } else if (protocol.equals("bridge")) {
+ sb.append(" <span class=\"label label-primary\">"
+ + "Bridges</span>");
+ } else if (protocol.equals("<OR>")) {
+ sb.append(" <span class=\"label label-info\">"
+ + "<OR></span>");
+ } else {
+ sb.append(" <span class=\"label label-info\">"
+ + protocol + "</span>");
+ }
}
}
- sb.append(", " + news.getDescription());
+ if (news.isUnknown()) {
+ sb.append(" <span class=\"label label-default\">"
+ + "Unknown</span>");
+ }
+ sb.append("<br>");
+ sb.append(news.getDescription());
+ sb.append("<br>");
if (news.getLinks() != null && news.getLinks().length > 0) {
int written = 0;
sb.append(" (");
@@ -98,7 +135,7 @@ public class NewsServlet extends HttpServlet {
}
sb.append("</p>");
String[] formattedNews = new String[] { sb.toString() };
- for (Map.Entry<String, String> category : cutOffDates.entrySet()) {
+ for (Map.Entry<String, String[]> category : cutOffDates.entrySet()) {
if (news.getStart().compareTo(category.getKey()) >= 0) {
newsByCategory.get(category.getValue()).add(formattedNews);
break;
@@ -107,7 +144,7 @@ public class NewsServlet extends HttpServlet {
}
/* Remove categories without news. */
- for (String category : cutOffDates.values()) {
+ for (String[] category : cutOffDates.values()) {
if (newsByCategory.get(category).isEmpty()) {
newsByCategory.remove(category);
}
diff --git a/website/web/WEB-INF/news.jsp b/website/web/WEB-INF/news.jsp
index 61c81b0..b99e260 100644
--- a/website/web/WEB-INF/news.jsp
+++ b/website/web/WEB-INF/news.jsp
@@ -6,6 +6,7 @@
<title>Tor Metrics</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link href="css/stylesheet-ltr.css" type="text/css" rel="stylesheet">
+ <link href="css/bootstrap.min.css" type="text/css" rel="stylesheet">
<link href="images/favicon.ico" type="image/x-icon" rel="shortcut icon">
</head>
<body>
@@ -33,8 +34,20 @@ of data, rather than just dogma or perspective."
<h3>News</h3>
<br>
+<p>We collect reports of events and aggregate them here for your convenience.
+The process is usually pretty informal.
+Someone tells us of an event, reports it to us, and we aggregate them here.
+If you know of any event that may have caused a measurement anomaly, help us add
+it to this list.</p>
+
+<c:forEach var="category" items="${news}">
+<a href="#${category.key[1]}">${category.key[0]}</a> |
+</c:forEach>
+<br>
+
<c:forEach var="category" items="${news}">
-<h3>${category.key}</h3>
+<a name="${category.key[1]}"></a>
+<h3>${category.key[0]}</h3>
<c:forEach var="entry" items="${category.value}">
<p>${entry[0]}</p>
</c:forEach>
diff --git a/website/web/css/bootstrap.min.css b/website/web/css/bootstrap.min.css
new file mode 100644
index 0000000..ed3905e
--- /dev/null
+++ b/website/web/css/bootstrap.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;fo
nt-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:
auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px so
lid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\
270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:bef
ore{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:b
efore{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:befo
re{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{con
tent:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bu
llhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{co
ntent:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.gly
phicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}
.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\
e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hambu
rger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon
-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6
px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weigh
t:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-c
apitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px
;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height
:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#3
33;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg
-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{rig
ht:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6
{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33
333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offs
et-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-
push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.666666
67%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667
%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid
#ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;di
splay:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{bac
kground-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>t
d,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin
-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr
>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[ty
pe=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-p
laceholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-g
roup-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disable
d],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .f
orm-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-con
trol-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color
:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error
.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-
inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-ali
gn:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba
(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-def
ault:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggl
e.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;bo
rder-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.b
tn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;
border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning
:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-dang
er.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm
{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;wid
th:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-deco
ration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bott
om:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last
-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.b
tn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-chi
ld){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle
=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height
:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon
{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:no
t(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-dec
oration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-ta
bs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-
cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent
;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.
container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;bord
er-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15
px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .rad
io label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left
;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd
}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:f
ocus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>
.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .na
vbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color
:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pag
ination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3p
x;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{posit
ion:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-
1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;paddin
g:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9ed
f7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:ce
nter;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:prog
ress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-i
mage:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-dang
er{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{ver
tical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;b
ackground-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:
hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d
9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-g
roup-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-dange
r.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.
panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-respo
nsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-
child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,
.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>t
foot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px sol
id #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tf
oot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-
child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd
}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer
+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-da
nger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filt
er:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:pa
dding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content
{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-
style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276
px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;
border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.
arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-
100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-i
mage:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carouse
l-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indica
tors .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container
:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!impo
rtant}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width
:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!i
mportant}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:non
e!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
+/*# sourceMappingURL=bootstrap.min.css.map */
\ No newline at end of file
1
0
commit bdfca8e75e23c3dd29e1fb6eca7ae835d26acde4
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Mon Dec 12 12:16:33 2016 +0100
Rip out metrics table.
---
.../org/torproject/metrics/web/IndexServlet.java | 246 +--------------------
website/web/WEB-INF/about.jsp | 6 +-
website/web/WEB-INF/index.jsp | 86 ++-----
3 files changed, 25 insertions(+), 313 deletions(-)
diff --git a/website/src/org/torproject/metrics/web/IndexServlet.java b/website/src/org/torproject/metrics/web/IndexServlet.java
index 576bac2..f365cbb 100644
--- a/website/src/org/torproject/metrics/web/IndexServlet.java
+++ b/website/src/org/torproject/metrics/web/IndexServlet.java
@@ -4,261 +4,23 @@
package org.torproject.metrics.web;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-@SuppressWarnings("serial")
public class IndexServlet extends HttpServlet {
- private static final String[][] knownTags = new String[][] {
- { "cl", "Clients" },
- { "rl", "Relays" },
- { "br", "Bridges" },
- { "pt", "Pluggable transports" },
- { "hs", "Hidden services" },
- { "bw", "Bandwidth" },
- { "pf", "Performance" },
- { "dv", "Diversity" }
- };
- private static final String[] defaultTags =
- new String[] { "cl", "rl", "br", "pt", "hs", "bw", "pf", "dv" };
-
- private static final String[][] knownTypes = new String[][] {
- { "gr", "Graph" },
- { "tb", "Table" },
- { "ln", "Link" },
- { "dt", "Data" }
- };
- private static final String[] defaultTypes =
- new String[] { "gr", "tb", "ln", "dt" };
-
- private static final String[][] knownLevels = new String[][] {
- { "bs", "Basic" },
- { "ad", "Advanced" }
- };
- private static final String[] defaultLevels = new String[] { "bs" };
-
- private static final String[][] knownOrders = new String[][] {
- { "name", "Name" },
- { "tags", "Tags" },
- { "type", "Type" },
- { "level", "Level" },
- { "shuffle", "None (shuffle)" }
- };
- private static final String[] defaultOrders = new String[] { "type" };
-
- private List<Metric> availableMetrics;
-
- @Override
- public void init() throws ServletException {
- this.availableMetrics = new ArrayList<Metric>();
- for (org.torproject.metrics.web.Metric metric
- : MetricsProvider.getInstance().getMetricsList()) {
- this.availableMetrics.add(new Metric(metric.getId() + ".html",
- metric.getTitle(), metric.getTags(), metric.getType(),
- metric.getLevel()));
- }
- }
+ private static final long serialVersionUID = -5156539049907533057L;
@Override
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
- @SuppressWarnings("rawtypes")
- Map parameterMap = request.getParameterMap();
- BitSet requestedTags = this.parseParameter(
- (String[]) parameterMap.get("tag"), knownTags, defaultTags);
- BitSet requestedTypes = this.parseParameter(
- (String[]) parameterMap.get("type"), knownTypes, defaultTypes);
- BitSet requestedLevels = this.parseParameter(
- (String[]) parameterMap.get("level"), knownLevels, defaultLevels);
- BitSet requestedOrder = this.parseParameter(
- (String[]) parameterMap.get("order"), knownOrders, defaultOrders);
- request.setAttribute("tags", this.formatParameter(knownTags,
- requestedTags));
- request.setAttribute("types", this.formatParameter(knownTypes,
- requestedTypes));
- request.setAttribute("levels", this.formatParameter(knownLevels,
- requestedLevels));
- request.setAttribute("order", this.formatParameter(knownOrders,
- requestedOrder));
- List<Metric> filteredAndOrderedMetrics = this.filterMetrics(
- requestedTags, requestedTypes, requestedLevels);
- this.orderMetrics(filteredAndOrderedMetrics, requestedOrder);
- request.setAttribute("results", this.formatMetrics(
- filteredAndOrderedMetrics));
+
+ /* Forward the request to the JSP that does all the hard work. */
request.getRequestDispatcher("WEB-INF/index.jsp").forward(request,
response);
}
-
- private BitSet parseParameter(String[] unparsedValues,
- String[][] knownValues, String[] defaultValues) {
- BitSet result = new BitSet();
- if (unparsedValues == null || unparsedValues.length == 0
- || unparsedValues.length > knownValues.length) {
- unparsedValues = defaultValues;
- }
- Set<String> requestedValues =
- new HashSet<String>(Arrays.asList(unparsedValues));
- for (int i = 0; i < knownValues.length; i++) {
- if (requestedValues.contains(knownValues[i][0])) {
- result.set(i);
- }
- }
- return result;
- }
-
- private String[][] formatParameter(String[][] strings, BitSet bitSet) {
- String[][] formattedParameter = new String[strings.length][];
- for (int i = 0; i < formattedParameter.length; i++) {
- String[] formatted = new String[] { strings[i][0], strings[i][1],
- "" };
- if (bitSet.get(i)) {
- formatted[2] = " checked";
- }
- formattedParameter[i] = formatted;
- }
- return formattedParameter;
- }
-
- private static class Metric {
-
- private String url;
-
- private String name;
-
- private BitSet tags;
-
- private BitSet type;
-
- private BitSet level;
-
- private Metric(String url, String name, String[] tagStrings,
- String typeString, String levelString) {
- this.url = url;
- this.name = name;
- this.tags = this.convertStringsToBitSet(knownTags, tagStrings);
- this.type = this.convertStringToBitSet(knownTypes, typeString);
- this.level = this.convertStringToBitSet(knownLevels, levelString);
- }
-
- private BitSet convertStringsToBitSet(String[][] knownKeysAndValues,
- String[] givenKeyStrings) {
- BitSet result = new BitSet(knownKeysAndValues.length);
- Set<String> keys = new HashSet<String>(Arrays.asList(
- givenKeyStrings));
- for (int i = 0; i < knownKeysAndValues.length; i++) {
- if (keys.contains(knownKeysAndValues[i][1])) {
- result.set(i);
- }
- }
- if (result.cardinality() != givenKeyStrings.length) {
- throw new RuntimeException("Unknown key(s): " + keys);
- }
- return result;
- }
-
- private BitSet convertStringToBitSet(String[][] knownKeysAndValues,
- String givenKeyString) {
- return this.convertStringsToBitSet(knownKeysAndValues,
- new String[] { givenKeyString });
- }
-
- private String[] toStrings() {
- return new String[] { this.url, this.name,
- this.convertBitSetToString(knownTags, this.tags),
- this.convertBitSetToString(knownTypes, this.type),
- this.convertBitSetToString(knownLevels, this.level) };
- }
-
- private String convertBitSetToString(String[][] knownKeysAndValues,
- BitSet bitSet) {
- StringBuilder sb = new StringBuilder();
- int index = -1;
- while ((index = bitSet.nextSetBit(index + 1)) >= 0) {
- sb.append(", " + knownKeysAndValues[index][1]);
- }
- return sb.substring(Math.min(sb.length(), 2));
- }
- }
-
- private List<Metric> filterMetrics(BitSet requestedTags,
- BitSet requestedTypes, BitSet requestedLevels) {
- List<Metric> filteredMetrics = new ArrayList<Metric>();
- for (Metric metric : availableMetrics) {
- if (requestedTags.intersects(metric.tags)
- && requestedTypes.intersects(metric.type)
- && requestedLevels.intersects(metric.level)) {
- filteredMetrics.add(metric);
- }
- }
- return filteredMetrics;
- }
-
- private void orderMetrics(List<Metric> resultMetrics,
- BitSet requestedOrder) {
- switch (requestedOrder.nextSetBit(0)) {
- case 0:
- Collections.sort(resultMetrics, new Comparator<Metric>() {
- public int compare(Metric first, Metric second) {
- return first.name.compareTo(second.name);
- }
- });
- break;
- case 1:
- Collections.sort(resultMetrics, new Comparator<Metric>() {
- public int compare(Metric first, Metric second) {
- return compareTwoBitSets(first.tags, second.tags);
- }
- });
- break;
- case 2:
- Collections.sort(resultMetrics, new Comparator<Metric>() {
- public int compare(Metric first, Metric second) {
- return compareTwoBitSets(first.type, second.type);
- }
- });
- break;
- case 3:
- Collections.sort(resultMetrics, new Comparator<Metric>() {
- public int compare(Metric first, Metric second) {
- return compareTwoBitSets(first.level, second.level);
- }
- });
- break;
- default:
- Collections.shuffle(resultMetrics);
- break;
- }
- }
-
- private int compareTwoBitSets(BitSet first, BitSet second) {
- if (first.equals(second)) {
- return 0;
- }
- BitSet xor = (BitSet) first.clone();
- xor.xor(second);
- return xor.length() == second.length() ? -1 : 1;
- }
-
- private String[][] formatMetrics(
- List<Metric> filteredAndOrderedMetrics) {
- String[][] formattedMetrics =
- new String[filteredAndOrderedMetrics.size()][];
- for (int i = 0; i < formattedMetrics.length; i++) {
- formattedMetrics[i] = filteredAndOrderedMetrics.get(i).toStrings();
- }
- return formattedMetrics;
- }
}
+
diff --git a/website/web/WEB-INF/about.jsp b/website/web/WEB-INF/about.jsp
index 91a696b..a067674 100644
--- a/website/web/WEB-INF/about.jsp
+++ b/website/web/WEB-INF/about.jsp
@@ -9,11 +9,7 @@
<body>
<div class="center">
<div class="main-column">
- <h2><a href="/"><img src="images/metrics-logo.png" width="153"
-height="200" al
-t="Metrics logo"><img src="images/metrics-wordmark.png" width="384" height="50"
-alt="M
-etrics wordmark"></a></h2>
+ <h2><a href="/"><img src="images/metrics-logo.png" width="153" height="200" alt="Metrics logo"><img src="images/metrics-wordmark.png" width="384" height="50" alt="Metrics wordmark"></a></h2>
<br>
<p>"Tor metrics are the ammunition that lets Tor and other security
diff --git a/website/web/WEB-INF/index.jsp b/website/web/WEB-INF/index.jsp
index 6e06474..ad4b79f 100644
--- a/website/web/WEB-INF/index.jsp
+++ b/website/web/WEB-INF/index.jsp
@@ -30,77 +30,31 @@ of data, rather than just dogma or perspective."
<br>
<!-- Navigation end -->
- <p>Welcome to Tor Metrics, the primary place to learn interesting
- facts about the Tor network, the largest deployed anonymity
- network to date.
- If something can be measured safely, you'll find it here.*</p>
- <p><small>*And if you come across something that is missing here,
- please
- <a href="https://www.torproject.org/about/contact.html.en">let us
- know</a>.</small></p>
+ <p>Welcome! What would you like to know about the Tor network?</p>
<div>
-<div style="border:1px solid gray;border-radius:10px;padding:10px;float:left;overflow:hidden;margin-right:20px;">
-<form action="/">
-<p>
-<b>Tags</b><br>
-<c:forEach var="row" items="${tags}">
-<label><input name="tag" type="checkbox" value="${row[0]}" <c:if test="${fn:length(row[2]) > 0}"> checked</c:if>> ${row[1]}</label></br>
-</c:forEach>
-</p>
-<p>
-<b>Type</b></br>
-<c:forEach var="row" items="${types}">
-<label><input name="type" type="checkbox" value="${row[0]}" <c:if test="${fn:length(row[2]) > 0}"> checked</c:if>> ${row[1]}</label></br>
-</c:forEach>
-</p>
-<p>
-<b>Level</b></br>
-<c:forEach var="row" items="${levels}">
-<label><input name="level" type="checkbox" value="${row[0]}" <c:if test="${fn:length(row[2]) > 0}"> checked</c:if>> ${row[1]}</label></br>
-</c:forEach>
-</p>
-<p>
-<b>Order</b></br>
-<c:forEach var="row" items="${order}">
-<label><input name="order" type="radio" value="${row[0]}" <c:if test="${fn:length(row[2]) > 0}"> checked</c:if>> ${row[1]}</label></br>
-</c:forEach>
-</p>
-<p>
-<input type="submit" value="Update">
-</p>
-</form>
-</div>
+<a href="userstats-relay-country.html"><h3>Users</h3></a>
+<p>Where are Tor users from? How do they connect to Tor?</p>
-<div style="overflow:hidden;">
-<style>
-table {
- border-spacing: 10px;
-}
-</style>
-<table>
-<thead>
-<tr>
-<th>Name</th>
-<th>Tags</th>
-<th>Type</th>
-<th>Level</th>
-</tr>
-</thead>
-<tbody>
-<c:forEach var="row" items="${results}">
-<tr>
-<td><a href="${row[0]}">${row[1]}</a></td>
-<td>${row[2]}</td>
-<td>${row[3]}</td>
-<td>${row[4]}</td>
-</tr>
-</c:forEach>
-</tbody>
-</table>
-</div>
+<a href="networksize.html"><h3>Relays and Bridges</h3></a>
+<p>How many relays and bridges are online? What do we know about them?</p>
+
+<a href="bandwidth.html"><h3>Traffic</h3></a>
+<p>How much traffic can the Tor network handle? How much traffic is there?</p>
+
+<a href="torperf.html"><h3>Performance</h3></a>
+<p>How fast and reliable is the Tor network?</p>
+
+<a href="hidserv-dir-onions-seen.html"><h3>Onion Services</h3></a>
+<p>How many onion services are there? How much traffic do they pull?</p>
+
+<h3>Downloads (coming soon)</h3>
+<p>How many downloads of Tor applications are there? How many updates?</p>
</div>
+<p>Let us know if we're missing anything, or if we should measure something
+else.</p>
+
</div>
</div>
<div class="bottom" id="bottom">
1
0
commit 8b92d9d4d18fcaf4f0c6d595bddea9880f8c4f19
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Wed Dec 14 19:52:10 2016 +0100
Update contents on About page.
---
website/web/WEB-INF/about.jsp | 268 +++---------------------------------------
1 file changed, 15 insertions(+), 253 deletions(-)
diff --git a/website/web/WEB-INF/about.jsp b/website/web/WEB-INF/about.jsp
index c169969..f16a114 100644
--- a/website/web/WEB-INF/about.jsp
+++ b/website/web/WEB-INF/about.jsp
@@ -29,266 +29,28 @@ of data, rather than just dogma or perspective."
<br>
<!-- Navigation end -->
-<h3>Frequently used terms</h3>
-<br>
+<h1>About</h1>
-<a name="advertised-bandwidth"></a>
-<p><b><a href="#advertised-bandwidth">advertised bandwidth:</a></b> the
-volume of traffic, both incoming and outgoing, that a
-<a href="#relay">relay</a> is willing to sustain, as configured by the
-operator and claimed to be observed from recent data transfers.</p>
+<p>Tor metrics are updated daily to provide transparency for Tor users, give
+feedback for developers, and measure evidence of network anomalies.</p>
-<a name="bandwidth-history"></a>
-<p><b><a href="#bandwidth-history">bandwidth history:</a></b> the volume
-of incoming and/or outgoing traffic that a <a href="#relay">relay</a>
-claims to have handled on behalf of <a href="#client">clients</a>.</p>
+<h2>Philosophy</h2>
-<a name="bridge"></a>
-<p><b><a href="#bridge">bridge:</a></b> a <a href="#relay">relay</a> whose
-existence is non-public and which can therefore provide access for blocked
-<a href="#client">clients</a>, often in combination with
-<a href="#pluggable-transport">pluggable transports</a>, which registers
-itself with the <a href="#bridge-authority">bridge authority</a>.</p>
+<p>We only use public, non-sensitive data for metrics. Each metric goes through
+a rigorous review and discussion process before appearing here. We never publish
+statistics—or aggregate statistics—of sensitive data, such as
+unencrypted contents of traffic.</p>
-<a name="bridge-authority"></a>
-<p><b><a href="#bridge-authority">bridge authority:</a></b> a
-special-purpose <a href="#relay">relay</a> that maintains a list of
-bridges as input for external bridge distribution mechanisms (for example,
-<a href="https://bridges.torproject.org/">BridgeDB</a>).</p>
+<h2>Contributing</h2>
-<a name="circuit"></a>
-<p><b><a href="#circuit">circuit:</a></b> a path through the Tor network
-built by <a href="#client">clients</a> consisting of at most one
-<a href="#bridge">bridge</a> and at least one
-<a href="#relay">relay</a>.</p>
+<p>Collecting and processing new data won't likely happen without your help! If
+you really want to see something measured here, we would be happy to work with
+you. (Link to Trac wiki page)</p>
-<a name="client"></a>
-<p><b><a href="#client">client:</a></b> a node in the Tor network,
-typically running on behalf of one user, that routes application
-connections over a series of <a href="#relay">relays</a>.</p>
+<h2>Contact</h2>
-<a name="consensus"></a>
-<p><b><a href="#consensus">consensus:</a></b> a single document compiled
-and voted on by the <a href="#directory-authority">directory
-authorities</a> once per hour, ensuring that all
-<a href="#client">clients</a> have the same information about the
-<a href="#relay">relays</a> that make up the Tor network.</p>
-
-<a name="consensus-weight"></a>
-<p><b><a href="#consensus-weight">consensus weight:</a></b> a value
-assigned to a <a href="#relay">relay</a> that is based on bandwidth
-observed by the relay and bandwidth measured by the
-<a href="#directory-authority">directory authorities</a>, included in the
-hourly published <a href="#consensus">consensus</a>, and used by
-<a href="#client">clients</a> to select relays for their
-<a href="#circuit">circuits</a>.</p>
-
-<a name="directory-authority"></a>
-<p><b><a href="#directory-authority">directory authority:</a></b> a
-special-purpose <a href="#relay">relay</a> that maintains a list of
-currently-running relays and periodically publishes a
-<a href="#consensus">consensus</a> together with the other directory
-authorities.</p>
-
-<a name="directory-mirror"></a>
-<p><b><a href="#directory-mirror">directory mirror:</a></b> a
-<a href="#relay">relay</a> that provides a recent copy of directory
-information to clients, in order to reduce the load on
-<a href="#directory-authority">directory authorities</a>.</p>
-
-<a name="hidden-service"></a>
-<p><b><a href="#hidden-service">hidden service:</a></b> a location-hidden
-service (for example, a website or instant-messaging server) that is only
-accessible via the Tor network.</p>
-
-<a name="pluggable-transport"></a>
-<p><b><a href="#pluggable-transport">pluggable transport:</a></b> an
-alternative transport protocol provided by <a href="#bridge">bridges</a>
-and used by <a href="#client">clients</a> to circumvent transport-level
-blockings (for example, by ISPs or governments).</p>
-
-<a name="relay"></a>
-<p><b><a href="#relay">relay:</a></b> a publicly-listed node in the Tor
-network that forwards traffic on behalf of <a href="#client">clients</a>,
-and that registers itself with the
-<a href="#directory-authority">directory authorities</a>.</p>
-
-<a name="relay-flag"></a>
-<p><b><a href="#relay-flag">relay flag:</a></b> a special
-(dis-)qualification of <a href="#relay">relays</a> for circuit positions
-(for example, "Guard", "Exit", "BadExit"), circuit properties (for
-example, "Fast", "Stable"), or roles (for example, "Authority", "HSDir"),
-as assigned by the <a href="#directory-authority">directory
-authorities</a> and further defined in the
-<a href="https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt">directory
-protocol specification</a>.</p>
-
-<h3>Frequently asked questions</h3>
-<br>
-
-<div style="line-height: 18pt;">
-<p>
-<b>Q: How do you obtain all these facts in an anonymity network without
-hurting user privacy?</b><br>
-A: The metrics on this website are based on different data sources in the
-Tor network.
-Some of these data sources are not sensitive at all, like properties and
-capabilities of a relay.
-Others are more sensitive, like statistics on fetched directory listings
-by country.
-But others are simply too sensitive to gather at all, like contents of
-unencrypted connections leaving the Tor network, so we don't have metrics
-on those.<br>
-We wrote a
-<a href="http://freehaven.net/anonbib/#wecsr10measuring-tor">research
-paper</a> where we describe how we measure potentially sensitive data in
-the Tor network.
-Whenever we plan to add new data, this plan needs to go through a rigorous
-process of writing a
-<a href="https://gitweb.torproject.org/torspec.git/tree/proposals/001-process.txt">proposal
-document</a>, which is usually discussed on the
-<a href="https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-dev">public
-development list</a>, and publicly reviewing code patches on the
-<a href="https://trac.torproject.org/projects/tor">bug tracker</a>.
-Furthermore, as a core principle, we only use data for metrics that have
-been made publicly available:
-if the raw data are too sensitive to publish, then we shouldn't even
-publish aggregate statistics of it.
-See the <a href="https://collector.torproject.org/">CollecTor service</a>
-that we use as single data source for all graphs and tables on this
-website.
-</p>
-<p>
-<b>Q: How do you know <a href="network.html">how many servers there are in
-the network</a>, how many of them permit exiting, etc.?<br></b>
-A: The servers in the Tor network, called relays and bridges, send a
-document with properties and capabilities to a set of central directory
-servers.
-These directory servers perform some reachability tests and publish a list
-of running servers.
-All we have to do is throw these documents into a database and run
-aggregation functions on it.
-</p>
-<p>
-<b>Q: How do you know <a href="bandwidth.html">how much bandwidth is
-advertised and consumed</a> in the network?</b>
-<br>
-A: Relays and bridges report bandwidth numbers to the central directory
-servers, both how much bandwidth they advertise and how much is used up by
-clients.
-</p>
-<p>
-<b>Q: How do you measure <a href="bubbles.html">diversity of relays</a> in
-the network?</b>
-<br>
-A: We resolve relay IP addresses to country codes and autonomous system
-numbers using <a href="https://www.maxmind.com/en/opensource">MaxMind's
-open source databases</a>.
-That gives us a rough idea whether there are certain countries or Internet
-providers running larger parts of the Tor network than others.
-</p>
-<p>
-<b>Q: How do you know <a href="users.html">how many users</a> there are in
-the network?</b>
-<br>
-A: We don't actually count users but directory traffic induced by Tor
-clients.
-Clients periodically need to update their view on the network, and by
-counting those requests we can make some rough estimates how many users
-there are.
-If you want to learn more, there's a more detailed document available
-dubbed
-<a href="https://gitweb.torproject.org/metrics-web.git/tree/doc/users-q-and-a.txt">Questions
-and answers about user statistics</a>.
-We also wrote a technical report titled
-<a href="https://research.torproject.org/techreports/counting-daily-bridge-users-201…">Counting
-daily bridge users</a> which is very related.
-</p>
-<p>
-<b>Q: How do you <a href="performance.html">measure performance</a> in the
-network?</b>
-<br>
-A: We run our own measurements using a tool called
-<a href="https://gitweb.torproject.org/torperf.git">Torperf</a>.
-This tool fetches files of three different sizes over the Tor network and
-measures how long that takes.
-</p>
-<p>
-<b>Q: How often are graphs updated?</b>
-<br>
-A: The graphs and tables on this website are updated multiple times per
-day.
-However, some graphs have the last few days cut off, because we don't have
-enough data available yet.
-It simply takes time to report, collect, and process all the data.
-</p>
-<p>
-<b>Q: Are the raw numbers behind graphs available for download?</b>
-<br>
-A: Yes, all raw numbers are available in <a href="stats/">comma-separated
-value files (.csv)</a>, which are further explained on the "Data:" pages,
-e.g., <a href="https://metrics.torproject.org/servers-data.html">"Data:
-Number of relays and bridges"</a>.
-In addition to that, the raw data behind those .csv files are available
-via the <a href="https://collector.torproject.org/">CollecTor service</a>.
-If you do something cool with either the .csv files or the raw data,
-please drop us a note, so that we may add a link here.
-</p>
-<p>
-<b>Q: How can I request a new graph or table?</b>
-<br>
-A: Please open a ticket in the
-<a href="https://trac.torproject.org/projects/tor">bug tracker</a> using
-component "Metrics Website".
-But please understand that adding a new graph or table may be harder than
-it seems.
-The following categories of feature requests may help you assess how
-likely it is that we implement your suggestion and how long it may take.
-Of course, you can always influence both likelihood and time to get your
-graph or table added by helping out!
-<ol>
-<li>Adding a link to a related project that does something cool with Tor
-network data is easiest.
-These links can be pretty useful, because somebody might pick up the idea
-and write a patch to include a fully customizable graph or table for this
-website.
-Adding a link is usually done within a day or two.</li>
-<li>Improving an existing graph or table is slightly more work.
-For example, you might suggest to add a new parameter or put another line
-on a graph.
-If the data for that is already available, this can be done within a
-couple of days, assuming somebody is free to do it.</li>
-<li>Adding a new graph or table based on existing, already processed data
-requires writing some graphing code in R and some HTML around it.
-This may take a few weeks.</li>
-<li>Adding a new graph or table based on raw data that needs processing
-takes quite some more work.
-This may require us to do some heavy database lifting, because we need to
-be sure that the processing code scales in the next few years.
-So, expect this to take a couple of months.</li>
-<li>Finally, adding a new metric based on newly gathered raw data, that
-is, new fields in descriptors or even new descriptors types, is most
-time-consuming.
-And to be honest, it is least likely to happen without your help.
-In addition to the significant development work, we may have to wait one
-or even two Tor release cycles to get the new code running on relays
-and/or bridges.
-Everything under one year is optimistic for this type of enhancement
-request.</li>
-</ol>
-</p>
-<p>
-<b>Q: Are there open feature requests or other issues related to this
-website, and where do I start writing code for it?</b>
-<br>
-A: The bug tracker has a list of
-<a href="https://trac.torproject.org/projects/tor/query?status=!closed&component=Met…">open
-tickets in the Metrics Website component</a>.
-The sources are
-<a href="https://gitweb.torproject.org/metrics-web.git/">available via
-Git</a>.
-</p>
-</div>
+<p>If you have any questions, contact us at <a
+href="mailto:metrics-team@lists.torproject.org">metrics-team(a)lists.torproject.org</a>.</p>
</div>
</div>
1
0