diff --git a/2018/10/12/gopherpalooza/go_surgery.htm b/2018/10/12/gopherpalooza/go_surgery.htm index b34f2b9..45a703c 100644 --- a/2018/10/12/gopherpalooza/go_surgery.htm +++ b/2018/10/12/gopherpalooza/go_surgery.htm @@ -1,5 +1,5 @@ - + Go surgery @@ -32,10 +32,10 @@ -
+
-
+

Go surgery

A goroutine and its innards

12 October 2018

@@ -60,7 +60,7 @@

12 October 2018

-
+

About myself

@@ -85,7 +85,7 @@

About myself

-
+

Why might this talk be important?

@@ -432,7 +432,7 @@

Pthread program

-
+

Pthread program continued

@@ -461,7 +461,7 @@

Pthread program continued

-
+

Perhaps looks similar?

@@ -501,7 +501,7 @@

Perhaps looks similar?

-
+

Standing on the shoulder of giants

@@ -528,7 +528,7 @@

Standing on the shoulder of giants

-
+

Goroutine states

@@ -536,7 +536,7 @@

Goroutine states

-
+

States of a goroutine

@@ -1074,9 +1074,8 @@

Simple leak detector

} <-time.After(2 * time.Second) // Reuse the buffer for next refresh - copy(buf[len(buf)-n:n], bytes.Repeat([]byte{0x00}, n)) - } -} + } +} @@ -1137,9 +1136,8 @@

Simple leak detector in action

} <-time.After(2 * time.Second) // Reuse the buffer for next refresh - copy(buf[len(buf)-n:n], bytes.Repeat([]byte{0x00}, n)) - } -} + } +} diff --git a/2018/10/12/gopherpalooza/leak_detector.go b/2018/10/12/gopherpalooza/leak_detector.go index 36f3b30..d0c0d28 100644 --- a/2018/10/12/gopherpalooza/leak_detector.go +++ b/2018/10/12/gopherpalooza/leak_detector.go @@ -17,6 +17,5 @@ func leakDetector() { } <-time.After(2 * time.Second) // Reuse the buffer for next refresh - copy(buf[len(buf)-n:n], bytes.Repeat([]byte{0x00}, n)) } } diff --git a/2018/10/12/gopherpalooza/leak_detector_in_use.go b/2018/10/12/gopherpalooza/leak_detector_in_use.go index 563088c..6f50381 100644 --- a/2018/10/12/gopherpalooza/leak_detector_in_use.go +++ b/2018/10/12/gopherpalooza/leak_detector_in_use.go @@ -35,6 +35,5 @@ func leakDetector() { } <-time.After(2 * time.Second) // Reuse the buffer for next refresh - copy(buf[len(buf)-n:n], bytes.Repeat([]byte{0x00}, n)) } } diff --git a/2018/10/22/ocjdbc/conn_with_annotation.java b/2018/10/22/ocjdbc/conn_with_annotation.java new file mode 100644 index 0000000..327b871 --- /dev/null +++ b/2018/10/22/ocjdbc/conn_with_annotation.java @@ -0,0 +1,6 @@ + java.sql.Connection conn = new Connection(originalConn, + // And passing this option to allow the spans + // to be annotated with the SQL queries. + // Please note that this could be a security concern + // since it could reveal personally identifying information. + Observability.OPTION_ANNOTATE_TRACES_WITH_SQL); diff --git a/2018/10/22/ocjdbc/exporters.java b/2018/10/22/ocjdbc/exporters.java new file mode 100644 index 0000000..6bf4c18 --- /dev/null +++ b/2018/10/22/ocjdbc/exporters.java @@ -0,0 +1,16 @@ +import io.opencensus.exporter.trace.jaeger.JaegerTraceExporter; +import io.opencensus.exporter.stats.prometheus.PrometheusStatsCollector; +import io.prometheus.client.exporter.HTTPServer; + +public static void enableObservability() throws Exception { + Observability.registerAllViews(); + + // The trace exporter, for this demo we'll use Jaeger. + JaegerTraceExporter.createAndRegister("http://127.0.0.1:14268/api/traces", "ocjdbc-demo"); + + // The metrics exporter. + PrometheusStatsCollector.createAndRegister(); + + // Run the server as a daeon on address "localhost:8889". + HTTPServer server = new HTTPServer("localhost", 8889); +} diff --git a/2018/10/22/ocjdbc/import.java b/2018/10/22/ocjdbc/import.java new file mode 100644 index 0000000..c97503d --- /dev/null +++ b/2018/10/22/ocjdbc/import.java @@ -0,0 +1,16 @@ +import io.opencensus.integration.ocjdbc.Connection; +import io.opencensus.integration.ocjdbc.Observability; + +public static void main(String ...args) { + // After you've enabled your connection, we'll now wrap it + java.sql.Connection conn = new Connection(originalConn); + + // Continue using your connection like you did in your normal programs +} + +public static void enableObservability() { + // Enable observability with OpenCensus + Observability.registerAllViews(); + + // Now create the trace and metrics exporters +} diff --git a/2018/10/22/ocjdbc/maven.xml b/2018/10/22/ocjdbc/maven.xml new file mode 100644 index 0000000..05ffea4 --- /dev/null +++ b/2018/10/22/ocjdbc/maven.xml @@ -0,0 +1,5 @@ + + io.opencensus.integration + opencensus-ocjdbc + 0.2.0 + diff --git a/2018/10/22/ocjdbc/ocjdbc-metrics-all.png b/2018/10/22/ocjdbc/ocjdbc-metrics-all.png new file mode 100644 index 0000000..7f1bab7 Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc-metrics-all.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc-metrics-calls.png b/2018/10/22/ocjdbc/ocjdbc-metrics-calls.png new file mode 100644 index 0000000..277733f Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc-metrics-calls.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc-metrics-latency-bucket.png b/2018/10/22/ocjdbc/ocjdbc-metrics-latency-bucket.png new file mode 100644 index 0000000..5b7276f Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc-metrics-latency-bucket.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc-tracing-all.png b/2018/10/22/ocjdbc/ocjdbc-tracing-all.png new file mode 100644 index 0000000..c519d0e Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc-tracing-all.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc-tracing-single-with-sql.png b/2018/10/22/ocjdbc/ocjdbc-tracing-single-with-sql.png new file mode 100644 index 0000000..39f6d5f Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc-tracing-single-with-sql.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc-tracing-single-without-sql.png b/2018/10/22/ocjdbc/ocjdbc-tracing-single-without-sql.png new file mode 100644 index 0000000..19677fe Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc-tracing-single-without-sql.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc.htm b/2018/10/22/ocjdbc/ocjdbc.htm new file mode 100644 index 0000000..28e3794 --- /dev/null +++ b/2018/10/22/ocjdbc/ocjdbc.htm @@ -0,0 +1,477 @@ + + + + ocjdbc + + + + + + + + + + + + +
+ + +
+

ocjdbc

+

OpenCensus + JDBC

+

22 October 2018

+ +
+ + +

+ Emmanuel T Odeke +

+ + + +

+ Orijtech, Inc. +

+ + +
+ +
+ + + +
+ +

ocjdbc

+ +
+ + + +
+ +

What is it?

+ +
    + +
  • Type 4 Java driver wrapper for the Java Database Connectivity API
  • + +
  • instrumented for distributed tracing and metrics with OpenCensus
  • + +
  • OpenCensus(oc) + JDBC(jdbc) = ocjdbc
  • + +
+ +
+ +
+ + +
+ + + +
+ +

About OpenCensus

+ +
    + +
  • OpenCensus is a vendor agnostic single distribution of libraries for distributed tracing and metrics
  • + +
  • The work of a collective, talented and vibrant community
  • + +
  • Entirely open sourced rewrite of the observability systems that have powered Google's production systems for the past 10+ years
  • + +
  • Collect metrics and traces once, export to backends of your choice
  • + +
  • Exporters/backends include: AWS X-Ray, Google Stackdriver, SignalFx, Zipkin, Jaeger, Datadog, Prometheus, Honeycomb
  • + +
  • zPages for live introspection
  • + +
  • For microservices and monoliths alike!
  • + +
  • Implemented in C#, C++, Go, Java, Python, Node.js, PHP, Ruby
  • + +
  • Website: https://opencensus.io/
  • + +
  • Github: https://github.com/census-instrumentation
  • + +
+ + +
+ + + +
+ +

Observability for your JDBC using apps

+ +
+ + + +
+ +

Update your pom.xml file

+ +
+ + +
<dependency>
+    <groupId>io.opencensus.integration</groupId>
+    <artifactId>opencensus-ocjdbc</artifactId>
+    <version>0.2.0</version>
+</dependency>
+
+ + +
+ + +
+ + + +
+ +

Source code update

+ +
    + +
  • Just wrap your connection
  • + +
+ +
+ + +
import io.opencensus.integration.ocjdbc.Connection;
+import io.opencensus.integration.ocjdbc.Observability;
+
+public static void main(String ...args) {
+    // After you've enabled your connection, we'll now wrap it
+    java.sql.Connection conn = new Connection(originalConn);
+
+    // Continue using your connection like you did in your normal programs
+}
+
+public static void enableObservability() {
+    // Enable observability with OpenCensus
+    Observability.registerAllViews();
+
+    // Now create the trace and metrics exporters
+}
+
+ + +
+ + +
+ + + +
+ +

Now enable exporters to extract your traces and metrics

+ + + +
+ + +
import io.opencensus.exporter.trace.jaeger.JaegerTraceExporter;
+import io.opencensus.exporter.stats.prometheus.PrometheusStatsCollector;
+import io.prometheus.client.exporter.HTTPServer;
+
+public static void enableObservability() throws Exception {
+    Observability.registerAllViews();
+
+    // The trace exporter, for this demo we'll use Jaeger.
+    JaegerTraceExporter.createAndRegister("http://127.0.0.1:14268/api/traces", "ocjdbc-demo");
+
+    // The metrics exporter.
+    PrometheusStatsCollector.createAndRegister();
+
+    // Run the server as a daeon on address "localhost:8889".
+    HTTPServer server = new HTTPServer("localhost", 8889);
+}
+
+ + +
+ + +
+ + + +
+ +

Results

+ +
+ + + +
+ +

Traces

+ +
+ + + +
+ +

All traces

+ +
    + +
  • Navigate to the trace backend's UI
  • + +
+ +
+ +
+ + +
+ + + +
+ +

Individual trace

+ +
+ +
+ + +
+ + + +
+ +

Individual trace with SQL annotation enabled

+ +
    + +
  • PII risk so passed as an option
  • + +
+ +
+ + +
        java.sql.Connection conn = new Connection(originalConn,
+                                        // And passing this option to allow the spans
+                                        // to be annotated with the SQL queries.
+                                        // Please note that this could be a security concern
+                                        // since it could reveal personally identifying information.
+                                        Observability.OPTION_ANNOTATE_TRACES_WITH_SQL);
+
+ + +
+ +
+ +
+ + +
+ + + +
+ +

Metrics

+ +
+ + + +
+ +

Recorded metrics

+ +
    + +
  • Latency in milliseconds
  • + +
  • Number of calls
  • + +
  • Tags include: "method", "status", "error"
  • + +
  • Important to identify bottlenecks, slow queries, hotspots in your system
  • + +
  • Use them to automatically alert your teams and SREs if latency increases beyond a threshold, error rates etc
  • + +
+ + +
+ + + +
+ +

All metrics

+ +
+ +
+ + +
+ + + +
+ +

Calls

+ +
+ +
+ + +
+ + + +
+ +

Latency buckets

+ +
+ +
+ + +
+ + + +
+ +

Appreciation

+ + +

+ Great thanks for the collaboration and support from: +
+ + - Yang Song +
+ + - Bogdan Drutu +
+ + - Pritam Shah +
+ + - The entire OpenCensus community and ecosystem +

+ + + +
+ + + + + + + +
+

Thank you

+ +
+ + +

+ Emmanuel T Odeke +

+ + + +

+ Orijtech, Inc. +

+ + +
+ +
+ +
+ + + + + + + + + + + \ No newline at end of file diff --git a/2018/10/22/ocjdbc/ocjdbc.png b/2018/10/22/ocjdbc/ocjdbc.png new file mode 100644 index 0000000..20b71c0 Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc_files/css b/2018/10/22/ocjdbc/ocjdbc_files/css new file mode 100644 index 0000000..7f90dd7 --- /dev/null +++ b/2018/10/22/ocjdbc/ocjdbc_files/css @@ -0,0 +1,232 @@ +/* latin */ +@font-face { + font-family: 'Droid Sans Mono'; + font-style: normal; + font-weight: 400; + src: local('Droid Sans Mono Regular'), local('DroidSansMono-Regular'), url(https://fonts.gstatic.com/s/droidsansmono/v9/6NUO8FuJNQ2MbkrZ5-J8lKFrp7pRef2rUGIW9g.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(https://fonts.gstatic.com/s/opensans/v15/mem6YaGs126MiZpBA-UFUK0Udc1GAK6bt6o.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(https://fonts.gstatic.com/s/opensans/v15/mem6YaGs126MiZpBA-UFUK0ddc1GAK6bt6o.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(https://fonts.gstatic.com/s/opensans/v15/mem6YaGs126MiZpBA-UFUK0Vdc1GAK6bt6o.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(https://fonts.gstatic.com/s/opensans/v15/mem6YaGs126MiZpBA-UFUK0adc1GAK6bt6o.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(https://fonts.gstatic.com/s/opensans/v15/mem6YaGs126MiZpBA-UFUK0Wdc1GAK6bt6o.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(https://fonts.gstatic.com/s/opensans/v15/mem6YaGs126MiZpBA-UFUK0Xdc1GAK6bt6o.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), url(https://fonts.gstatic.com/s/opensans/v15/mem6YaGs126MiZpBA-UFUK0Zdc1GAK6b.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), url(https://fonts.gstatic.com/s/opensans/v15/memnYaGs126MiZpBA-UFUKXGUdhmIqOxjaPXZSk.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), url(https://fonts.gstatic.com/s/opensans/v15/memnYaGs126MiZpBA-UFUKXGUdhvIqOxjaPXZSk.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), url(https://fonts.gstatic.com/s/opensans/v15/memnYaGs126MiZpBA-UFUKXGUdhnIqOxjaPXZSk.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), url(https://fonts.gstatic.com/s/opensans/v15/memnYaGs126MiZpBA-UFUKXGUdhoIqOxjaPXZSk.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), url(https://fonts.gstatic.com/s/opensans/v15/memnYaGs126MiZpBA-UFUKXGUdhkIqOxjaPXZSk.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), url(https://fonts.gstatic.com/s/opensans/v15/memnYaGs126MiZpBA-UFUKXGUdhlIqOxjaPXZSk.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), url(https://fonts.gstatic.com/s/opensans/v15/memnYaGs126MiZpBA-UFUKXGUdhrIqOxjaPX.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFWJ0bf8pkAp6a.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFUZ0bf8pkAp6a.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFWZ0bf8pkAp6a.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFVp0bf8pkAp6a.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFWp0bf8pkAp6a.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFW50bf8pkAp6a.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFVZ0bf8pkAg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), url(https://fonts.gstatic.com/s/opensans/v15/mem5YaGs126MiZpBA-UNirkOX-hpKKSTj5PW.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), url(https://fonts.gstatic.com/s/opensans/v15/mem5YaGs126MiZpBA-UNirkOVuhpKKSTj5PW.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), url(https://fonts.gstatic.com/s/opensans/v15/mem5YaGs126MiZpBA-UNirkOXuhpKKSTj5PW.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), url(https://fonts.gstatic.com/s/opensans/v15/mem5YaGs126MiZpBA-UNirkOUehpKKSTj5PW.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), url(https://fonts.gstatic.com/s/opensans/v15/mem5YaGs126MiZpBA-UNirkOXehpKKSTj5PW.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), url(https://fonts.gstatic.com/s/opensans/v15/mem5YaGs126MiZpBA-UNirkOXOhpKKSTj5PW.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), url(https://fonts.gstatic.com/s/opensans/v15/mem5YaGs126MiZpBA-UNirkOUuhpKKSTjw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-metrics-all.png b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-metrics-all.png new file mode 100644 index 0000000..7f1bab7 Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-metrics-all.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-metrics-calls.png b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-metrics-calls.png new file mode 100644 index 0000000..277733f Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-metrics-calls.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-metrics-latency-bucket.png b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-metrics-latency-bucket.png new file mode 100644 index 0000000..5b7276f Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-metrics-latency-bucket.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-tracing-all.png b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-tracing-all.png new file mode 100644 index 0000000..c519d0e Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-tracing-all.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-tracing-single-with-sql.png b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-tracing-single-with-sql.png new file mode 100644 index 0000000..39f6d5f Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-tracing-single-with-sql.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-tracing-single-without-sql.png b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-tracing-single-without-sql.png new file mode 100644 index 0000000..19677fe Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc-tracing-single-without-sql.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc.png b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc.png new file mode 100644 index 0000000..20b71c0 Binary files /dev/null and b/2018/10/22/ocjdbc/ocjdbc_files/ocjdbc.png differ diff --git a/2018/10/22/ocjdbc/ocjdbc_files/play.js b/2018/10/22/ocjdbc/ocjdbc_files/play.js new file mode 100644 index 0000000..9bc112e --- /dev/null +++ b/2018/10/22/ocjdbc/ocjdbc_files/play.js @@ -0,0 +1,595 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
t
",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
","
"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);/*! jQuery UI - v1.10.2 - 2013-03-20 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.resizable.js +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("
").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css("left")),n=t(this.helper.css("top")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===n&&(e.left=t.left+(s.width-e.width),e.top=null),"nw"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidthe.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=e(this).data("ui-resizable"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e(["Top","Right","Left","Bottom"]).each(function(e,n){s[e]=t(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,"left")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery);// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +In the absence of any formal way to specify interfaces in JavaScript, +here's a skeleton implementation of a playground transport. + + function Transport() { + // Set up any transport state (eg, make a websocket connection). + return { + Run: function(body, output, options) { + // Compile and run the program 'body' with 'options'. + // Call the 'output' callback to display program output. + return { + Kill: function() { + // Kill the running program. + } + }; + } + }; + } + + // The output callback is called multiple times, and each time it is + // passed an object of this form. + var write = { + Kind: 'string', // 'start', 'stdout', 'stderr', 'end' + Body: 'string' // content of write or end status message + } + + // The first call must be of Kind 'start' with no body. + // Subsequent calls may be of Kind 'stdout' or 'stderr' + // and must have a non-null Body string. + // The final call should be of Kind 'end' with an optional + // Body string, signifying a failure ("killed", for example). + + // The output callback must be of this form. + // See PlaygroundOutput (below) for an implementation. + function outputCallback(write) { + } +*/ + +function HTTPTransport() { + 'use strict'; + + // TODO(adg): support stderr + + function playback(output, events) { + var timeout; + output({Kind: 'start'}); + function next() { + if (!events || events.length === 0) { + output({Kind: 'end'}); + return; + } + var e = events.shift(); + if (e.Delay === 0) { + output({Kind: 'stdout', Body: e.Message}); + next(); + return; + } + timeout = setTimeout(function() { + output({Kind: 'stdout', Body: e.Message}); + next(); + }, e.Delay / 1000000); + } + next(); + return { + Stop: function() { + clearTimeout(timeout); + } + } + } + + function error(output, msg) { + output({Kind: 'start'}); + output({Kind: 'stderr', Body: msg}); + output({Kind: 'end'}); + } + + var seq = 0; + return { + Run: function(body, output, options) { + seq++; + var cur = seq; + var playing; + $.ajax('/compile', { + type: 'POST', + data: {'version': 2, 'body': body}, + dataType: 'json', + success: function(data) { + if (seq != cur) return; + if (!data) return; + if (playing != null) playing.Stop(); + if (data.Errors) { + error(output, data.Errors); + return; + } + playing = playback(output, data.Events); + }, + error: function() { + error(output, 'Error communicating with remote server.'); + } + }); + return { + Kill: function() { + if (playing != null) playing.Stop(); + output({Kind: 'end', Body: 'killed'}); + } + }; + } + }; +} + +function SocketTransport() { + 'use strict'; + + var id = 0; + var outputs = {}; + var started = {}; + var websocket; + if (window.location.protocol == "http:") { + websocket = new WebSocket('ws://' + window.location.host + '/socket'); + } else if (window.location.protocol == "https:") { + websocket = new WebSocket('wss://' + window.location.host + '/socket'); + } + + websocket.onclose = function() { + console.log('websocket connection closed'); + } + + websocket.onmessage = function(e) { + var m = JSON.parse(e.data); + var output = outputs[m.Id]; + if (output === null) + return; + if (!started[m.Id]) { + output({Kind: 'start'}); + started[m.Id] = true; + } + output({Kind: m.Kind, Body: m.Body}); + } + + function send(m) { + websocket.send(JSON.stringify(m)); + } + + return { + Run: function(body, output, options) { + var thisID = id+''; + id++; + outputs[thisID] = output; + send({Id: thisID, Kind: 'run', Body: body, Options: options}); + return { + Kill: function() { + send({Id: thisID, Kind: 'kill'}); + } + }; + } + }; +} + +function PlaygroundOutput(el) { + 'use strict'; + + return function(write) { + if (write.Kind == 'start') { + el.innerHTML = ''; + return; + } + + var cl = 'system'; + if (write.Kind == 'stdout' || write.Kind == 'stderr') + cl = write.Kind; + + var m = write.Body; + if (write.Kind == 'end') { + m = '\nProgram exited' + (m?(': '+m):'.'); + } + + if (m.indexOf('IMAGE:') === 0) { + // TODO(adg): buffer all writes before creating image + var url = 'data:image/png;base64,' + m.substr(6); + var img = document.createElement('img'); + img.src = url; + el.appendChild(img); + return; + } + + // ^L clears the screen. + var s = m.split('\x0c'); + if (s.length > 1) { + el.innerHTML = ''; + m = s.pop(); + } + + m = m.replace(/&/g, '&'); + m = m.replace(//g, '>'); + + var needScroll = (el.scrollTop + el.offsetHeight) == el.scrollHeight; + + var span = document.createElement('span'); + span.className = cl; + span.innerHTML = m; + el.appendChild(span); + + if (needScroll) + el.scrollTop = el.scrollHeight - el.offsetHeight; + } +} + +(function() { + function lineHighlight(error) { + var regex = /prog.go:([0-9]+)/g; + var r = regex.exec(error); + while (r) { + $(".lines div").eq(r[1]-1).addClass("lineerror"); + r = regex.exec(error); + } + } + function highlightOutput(wrappedOutput) { + return function(write) { + if (write.Body) lineHighlight(write.Body); + wrappedOutput(write); + } + } + function lineClear() { + $(".lineerror").removeClass("lineerror"); + } + + // opts is an object with these keys + // codeEl - code editor element + // outputEl - program output element + // runEl - run button element + // fmtEl - fmt button element (optional) + // fmtImportEl - fmt "imports" checkbox element (optional) + // shareEl - share button element (optional) + // shareURLEl - share URL text input element (optional) + // shareRedirect - base URL to redirect to on share (optional) + // toysEl - toys select element (optional) + // enableHistory - enable using HTML5 history API (optional) + // transport - playground transport to use (default is HTTPTransport) + // enableShortcuts - whether to enable shortcuts (Ctrl+S/Cmd+S to save) (default is false) + function playground(opts) { + var code = $(opts.codeEl); + var transport = opts['transport'] || new HTTPTransport(); + var running; + + // autoindent helpers. + function insertTabs(n) { + // find the selection start and end + var start = code[0].selectionStart; + var end = code[0].selectionEnd; + // split the textarea content into two, and insert n tabs + var v = code[0].value; + var u = v.substr(0, start); + for (var i=0; i 0) { + curpos--; + if (el.value[curpos] == "\t") { + tabs++; + } else if (tabs > 0 || el.value[curpos] == "\n") { + break; + } + } + setTimeout(function() { + insertTabs(tabs); + }, 1); + } + + // NOTE(cbro): e is a jQuery event, not a DOM event. + function handleSaveShortcut(e) { + if (e.isDefaultPrevented()) return false; + if (!e.metaKey && !e.ctrlKey) return false; + if (e.key != "S" && e.key != "s") return false; + + e.preventDefault(); + + // Share and save + share(function(url) { + window.location.href = url + ".go?download=true"; + }); + + return true; + } + + function keyHandler(e) { + if (opts.enableShortcuts && handleSaveShortcut(e)) return; + + if (e.keyCode == 9 && !e.ctrlKey) { // tab (but not ctrl-tab) + insertTabs(1); + e.preventDefault(); + return false; + } + if (e.keyCode == 13) { // enter + if (e.shiftKey) { // +shift + run(); + e.preventDefault(); + return false; + } if (e.ctrlKey) { // +control + fmt(); + e.preventDefault(); + } else { + autoindent(e.target); + } + } + return true; + } + code.unbind('keydown').bind('keydown', keyHandler); + var outdiv = $(opts.outputEl).empty(); + var output = $('
').appendTo(outdiv);
+
+    function body() {
+      return $(opts.codeEl).val();
+    }
+    function setBody(text) {
+      $(opts.codeEl).val(text);
+    }
+    function origin(href) {
+      return (""+href).split("/").slice(0, 3).join("/");
+    }
+
+    var pushedEmpty = (window.location.pathname == "/");
+    function inputChanged() {
+      if (pushedEmpty) {
+        return;
+      }
+      pushedEmpty = true;
+      $(opts.shareURLEl).hide();
+      window.history.pushState(null, "", "/");
+    }
+    function popState(e) {
+      if (e === null) {
+        return;
+      }
+      if (e && e.state && e.state.code) {
+        setBody(e.state.code);
+      }
+    }
+    var rewriteHistory = false;
+    if (window.history && window.history.pushState && window.addEventListener && opts.enableHistory) {
+      rewriteHistory = true;
+      code[0].addEventListener('input', inputChanged);
+      window.addEventListener('popstate', popState);
+    }
+
+    function setError(error) {
+      if (running) running.Kill();
+      lineClear();
+      lineHighlight(error);
+      output.empty().addClass("error").text(error);
+    }
+    function loading() {
+      lineClear();
+      if (running) running.Kill();
+      output.removeClass("error").text('Waiting for remote server...');
+    }
+    function run() {
+      loading();
+      running = transport.Run(body(), highlightOutput(PlaygroundOutput(output[0])));
+    }
+
+    function fmt() {
+      loading();
+      var data = {"body": body()};
+      if ($(opts.fmtImportEl).is(":checked")) {
+        data["imports"] = "true";
+      }
+      $.ajax("/fmt", {
+        data: data,
+        type: "POST",
+        dataType: "json",
+        success: function(data) {
+          if (data.Error) {
+            setError(data.Error);
+          } else {
+            setBody(data.Body);
+            setError("");
+          }
+        }
+      });
+    }
+
+    var shareURL; // jQuery element to show the shared URL.
+    var sharing = false; // true if there is a pending request.
+    var shareCallbacks = [];
+    function share(opt_callback) {
+      if (opt_callback) shareCallbacks.push(opt_callback);
+
+      if (sharing) return;
+      sharing = true;
+
+      var sharingData = body();
+      $.ajax("/share", {
+        processData: false,
+        data: sharingData,
+        type: "POST",
+        contentType: "text/plain; charset=utf-8",
+        complete: function(xhr) {
+          sharing = false;
+          if (xhr.status != 200) {
+            alert("Server error; try again.");
+            return;
+          }
+          if (opts.shareRedirect) {
+            window.location = opts.shareRedirect + xhr.responseText;
+          }
+          var path = "/p/" + xhr.responseText;
+          var url = origin(window.location) + path;
+
+          for (var i = 0; i < shareCallbacks.length; i++) {
+            shareCallbacks[i](url);
+          }
+          shareCallbacks = [];
+
+          if (shareURL) {
+            shareURL.show().val(url).focus().select();
+
+            if (rewriteHistory) {
+              var historyData = {"code": sharingData};
+              window.history.pushState(historyData, "", path);
+              pushedEmpty = false;
+            }
+          }
+        }
+      });
+    }
+
+    $(opts.runEl).click(run);
+    $(opts.fmtEl).click(fmt);
+
+    if (opts.shareEl !== null && (opts.shareURLEl !== null || opts.shareRedirect !== null)) {
+      if (opts.shareURLEl) {
+        shareURL = $(opts.shareURLEl).hide();
+      }
+      $(opts.shareEl).click(function() {
+        share();
+      });
+    }
+
+    if (opts.toysEl !== null) {
+      $(opts.toysEl).bind('change', function() {
+        var toy = $(this).val();
+        $.ajax("/doc/play/"+toy, {
+          processData: false,
+          type: "GET",
+          complete: function(xhr) {
+            if (xhr.status != 200) {
+              alert("Server error; try again.");
+              return;
+            }
+            setBody(xhr.responseText);
+          }
+        });
+      });
+    }
+  }
+
+  window.playground = playground;
+})();
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+function initPlayground(transport) {
+	'use strict';
+
+	function text(node) {
+		var s = '';
+		for (var i = 0; i < node.childNodes.length; i++) {
+			var n = node.childNodes[i];
+			if (n.nodeType === 1) {
+				if (n.tagName === 'BUTTON') continue
+				if (n.tagName === 'SPAN' && n.className === 'number') continue;
+				if (n.tagName === 'DIV' || n.tagName == 'BR') {
+					s += "\n";
+				}
+				s += text(n);
+				continue;
+			}
+			if (n.nodeType === 3) {
+				s += n.nodeValue;
+			}
+		}
+		return s.replace('\xA0', ' '); // replace non-breaking spaces
+	}
+
+	// When presenter notes are enabled, the index passed
+	// here will identify the playground to be synced
+	function init(code, index) {
+		var output = document.createElement('div');
+		var outpre = document.createElement('pre');
+		var running;
+
+		if ($ && $(output).resizable) {
+			$(output).resizable({
+				handles: 	'n,w,nw',
+				minHeight:	27,
+				minWidth:	135,
+				maxHeight:	608,
+				maxWidth:	990
+			});
+		}
+
+		function onKill() {
+			if (running) running.Kill();
+			if (window.notesEnabled) updatePlayStorage('onKill', index);
+		}
+
+		function onRun(e) {
+			var sk = e.shiftKey || localStorage.getItem('play-shiftKey') === 'true';
+			if (running) running.Kill();
+			output.style.display = 'block';
+			outpre.innerHTML = '';
+			run1.style.display = 'none';
+			var options = {Race: sk};
+			running = transport.Run(text(code), PlaygroundOutput(outpre), options);
+			if (window.notesEnabled) updatePlayStorage('onRun', index, e);
+		}
+
+		function onClose() {
+			if (running) running.Kill();
+			output.style.display = 'none';
+			run1.style.display = 'inline-block';
+			if (window.notesEnabled) updatePlayStorage('onClose', index);
+		}
+
+		if (window.notesEnabled) {
+			playgroundHandlers.onRun.push(onRun);
+			playgroundHandlers.onClose.push(onClose);
+			playgroundHandlers.onKill.push(onKill);
+		}
+
+		var run1 = document.createElement('button');
+		run1.innerHTML = 'Run';
+		run1.className = 'run';
+		run1.addEventListener("click", onRun, false);
+		var run2 = document.createElement('button');
+		run2.className = 'run';
+		run2.innerHTML = 'Run';
+		run2.addEventListener("click", onRun, false);
+		var kill = document.createElement('button');
+		kill.className = 'kill';
+		kill.innerHTML = 'Kill';
+		kill.addEventListener("click", onKill, false);
+		var close = document.createElement('button');
+		close.className = 'close';
+		close.innerHTML = 'Close';
+		close.addEventListener("click", onClose, false);
+
+		var button = document.createElement('div');
+		button.classList.add('buttons');
+		button.appendChild(run1);
+		// Hack to simulate insertAfter
+		code.parentNode.insertBefore(button, code.nextSibling);
+
+		var buttons = document.createElement('div');
+		buttons.classList.add('buttons');
+		buttons.appendChild(run2);
+		buttons.appendChild(kill);
+		buttons.appendChild(close);
+
+		output.classList.add('output');
+		output.appendChild(buttons);
+		output.appendChild(outpre);
+		output.style.display = 'none';
+		code.parentNode.insertBefore(output, button.nextSibling);
+	}
+
+	var play = document.querySelectorAll('div.playground');
+	for (var i = 0; i < play.length; i++) {
+		init(play[i], i);
+	}
+}
+
+initPlayground(new SocketTransport());
diff --git a/2018/10/22/ocjdbc/ocjdbc_files/slides.js b/2018/10/22/ocjdbc/ocjdbc_files/slides.js
new file mode 100644
index 0000000..df10647
--- /dev/null
+++ b/2018/10/22/ocjdbc/ocjdbc_files/slides.js
@@ -0,0 +1,612 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var PERMANENT_URL_PREFIX = '/static/';
+
+var SLIDE_CLASSES = ['far-past', 'past', 'current', 'next', 'far-next'];
+
+var PM_TOUCH_SENSITIVITY = 15;
+
+var curSlide;
+
+/* ---------------------------------------------------------------------- */
+/* classList polyfill by Eli Grey
+ * (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */
+
+if (typeof document !== 'undefined' && !('classList' in document.createElement('a'))) {
+
+(function (view) {
+
+var
+    classListProp = 'classList'
+  , protoProp = 'prototype'
+  , elemCtrProto = (view.HTMLElement || view.Element)[protoProp]
+  , objCtr = Object
+    strTrim = String[protoProp].trim || function () {
+    return this.replace(/^\s+|\s+$/g, '');
+  }
+  , arrIndexOf = Array[protoProp].indexOf || function (item) {
+    for (var i = 0, len = this.length; i < len; i++) {
+      if (i in this && this[i] === item) {
+        return i;
+      }
+    }
+    return -1;
+  }
+  // Vendors: please allow content code to instantiate DOMExceptions
+  , DOMEx = function (type, message) {
+    this.name = type;
+    this.code = DOMException[type];
+    this.message = message;
+  }
+  , checkTokenAndGetIndex = function (classList, token) {
+    if (token === '') {
+      throw new DOMEx(
+          'SYNTAX_ERR'
+        , 'An invalid or illegal string was specified'
+      );
+    }
+    if (/\s/.test(token)) {
+      throw new DOMEx(
+          'INVALID_CHARACTER_ERR'
+        , 'String contains an invalid character'
+      );
+    }
+    return arrIndexOf.call(classList, token);
+  }
+  , ClassList = function (elem) {
+    var
+        trimmedClasses = strTrim.call(elem.className)
+      , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
+    ;
+    for (var i = 0, len = classes.length; i < len; i++) {
+      this.push(classes[i]);
+    }
+    this._updateClassName = function () {
+      elem.className = this.toString();
+    };
+  }
+  , classListProto = ClassList[protoProp] = []
+  , classListGetter = function () {
+    return new ClassList(this);
+  }
+;
+// Most DOMException implementations don't allow calling DOMException's toString()
+// on non-DOMExceptions. Error's toString() is sufficient here.
+DOMEx[protoProp] = Error[protoProp];
+classListProto.item = function (i) {
+  return this[i] || null;
+};
+classListProto.contains = function (token) {
+  token += '';
+  return checkTokenAndGetIndex(this, token) !== -1;
+};
+classListProto.add = function (token) {
+  token += '';
+  if (checkTokenAndGetIndex(this, token) === -1) {
+    this.push(token);
+    this._updateClassName();
+  }
+};
+classListProto.remove = function (token) {
+  token += '';
+  var index = checkTokenAndGetIndex(this, token);
+  if (index !== -1) {
+    this.splice(index, 1);
+    this._updateClassName();
+  }
+};
+classListProto.toggle = function (token) {
+  token += '';
+  if (checkTokenAndGetIndex(this, token) === -1) {
+    this.add(token);
+  } else {
+    this.remove(token);
+  }
+};
+classListProto.toString = function () {
+  return this.join(' ');
+};
+
+if (objCtr.defineProperty) {
+  var classListPropDesc = {
+      get: classListGetter
+    , enumerable: true
+    , configurable: true
+  };
+  try {
+    objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+  } catch (ex) { // IE 8 doesn't support enumerable:true
+    if (ex.number === -0x7FF5EC54) {
+      classListPropDesc.enumerable = false;
+      objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+    }
+  }
+} else if (objCtr[protoProp].__defineGetter__) {
+  elemCtrProto.__defineGetter__(classListProp, classListGetter);
+}
+
+}(self));
+
+}
+/* ---------------------------------------------------------------------- */
+
+/* Slide movement */
+
+function hideHelpText() {
+  document.getElementById('help').style.display = 'none';
+};
+
+function getSlideEl(no) {
+  if ((no < 0) || (no >= slideEls.length)) {
+    return null;
+  } else {
+    return slideEls[no];
+  }
+};
+
+function updateSlideClass(slideNo, className) {
+  var el = getSlideEl(slideNo);
+
+  if (!el) {
+    return;
+  }
+
+  if (className) {
+    el.classList.add(className);
+  }
+
+  for (var i in SLIDE_CLASSES) {
+    if (className != SLIDE_CLASSES[i]) {
+      el.classList.remove(SLIDE_CLASSES[i]);
+    }
+  }
+};
+
+function updateSlides() {
+  if (window.trackPageview) window.trackPageview();
+
+  for (var i = 0; i < slideEls.length; i++) {
+    switch (i) {
+      case curSlide - 2:
+        updateSlideClass(i, 'far-past');
+        break;
+      case curSlide - 1:
+        updateSlideClass(i, 'past');
+        break;
+      case curSlide:
+        updateSlideClass(i, 'current');
+        break;
+      case curSlide + 1:
+        updateSlideClass(i, 'next');
+        break;
+      case curSlide + 2:
+        updateSlideClass(i, 'far-next');
+        break;
+      default:
+        updateSlideClass(i);
+        break;
+    }
+  }
+
+  triggerLeaveEvent(curSlide - 1);
+  triggerEnterEvent(curSlide);
+
+  window.setTimeout(function() {
+    // Hide after the slide
+    disableSlideFrames(curSlide - 2);
+  }, 301);
+
+  enableSlideFrames(curSlide - 1);
+  enableSlideFrames(curSlide + 2);
+
+  updateHash();
+};
+
+function prevSlide() {
+  hideHelpText();
+  if (curSlide > 0) {
+    curSlide--;
+
+    updateSlides();
+  }
+
+  if (notesEnabled) localStorage.setItem('destSlide', curSlide);
+};
+
+function nextSlide() {
+  hideHelpText();
+  if (curSlide < slideEls.length - 1) {
+    curSlide++;
+
+    updateSlides();
+  }
+
+  if (notesEnabled) localStorage.setItem('destSlide', curSlide);
+};
+
+/* Slide events */
+
+function triggerEnterEvent(no) {
+  var el = getSlideEl(no);
+  if (!el) {
+    return;
+  }
+
+  var onEnter = el.getAttribute('onslideenter');
+  if (onEnter) {
+    new Function(onEnter).call(el);
+  }
+
+  var evt = document.createEvent('Event');
+  evt.initEvent('slideenter', true, true);
+  evt.slideNumber = no + 1; // Make it readable
+
+  el.dispatchEvent(evt);
+};
+
+function triggerLeaveEvent(no) {
+  var el = getSlideEl(no);
+  if (!el) {
+    return;
+  }
+
+  var onLeave = el.getAttribute('onslideleave');
+  if (onLeave) {
+    new Function(onLeave).call(el);
+  }
+
+  var evt = document.createEvent('Event');
+  evt.initEvent('slideleave', true, true);
+  evt.slideNumber = no + 1; // Make it readable
+
+  el.dispatchEvent(evt);
+};
+
+/* Touch events */
+
+function handleTouchStart(event) {
+  if (event.touches.length == 1) {
+    touchDX = 0;
+    touchDY = 0;
+
+    touchStartX = event.touches[0].pageX;
+    touchStartY = event.touches[0].pageY;
+
+    document.body.addEventListener('touchmove', handleTouchMove, true);
+    document.body.addEventListener('touchend', handleTouchEnd, true);
+  }
+};
+
+function handleTouchMove(event) {
+  if (event.touches.length > 1) {
+    cancelTouch();
+  } else {
+    touchDX = event.touches[0].pageX - touchStartX;
+    touchDY = event.touches[0].pageY - touchStartY;
+    event.preventDefault();
+  }
+};
+
+function handleTouchEnd(event) {
+  var dx = Math.abs(touchDX);
+  var dy = Math.abs(touchDY);
+
+  if ((dx > PM_TOUCH_SENSITIVITY) && (dy < (dx * 2 / 3))) {
+    if (touchDX > 0) {
+      prevSlide();
+    } else {
+      nextSlide();
+    }
+  }
+
+  cancelTouch();
+};
+
+function cancelTouch() {
+  document.body.removeEventListener('touchmove', handleTouchMove, true);
+  document.body.removeEventListener('touchend', handleTouchEnd, true);
+};
+
+/* Preloading frames */
+
+function disableSlideFrames(no) {
+  var el = getSlideEl(no);
+  if (!el) {
+    return;
+  }
+
+  var frames = el.getElementsByTagName('iframe');
+  for (var i = 0, frame; frame = frames[i]; i++) {
+    disableFrame(frame);
+  }
+};
+
+function enableSlideFrames(no) {
+  var el = getSlideEl(no);
+  if (!el) {
+    return;
+  }
+
+  var frames = el.getElementsByTagName('iframe');
+  for (var i = 0, frame; frame = frames[i]; i++) {
+    enableFrame(frame);
+  }
+};
+
+function disableFrame(frame) {
+  frame.src = 'about:blank';
+};
+
+function enableFrame(frame) {
+  var src = frame._src;
+
+  if (frame.src != src && src != 'about:blank') {
+    frame.src = src;
+  }
+};
+
+function setupFrames() {
+  var frames = document.querySelectorAll('iframe');
+  for (var i = 0, frame; frame = frames[i]; i++) {
+    frame._src = frame.src;
+    disableFrame(frame);
+  }
+
+  enableSlideFrames(curSlide);
+  enableSlideFrames(curSlide + 1);
+  enableSlideFrames(curSlide + 2);
+};
+
+function setupInteraction() {
+  /* Clicking and tapping */
+
+  var el = document.createElement('div');
+  el.className = 'slide-area';
+  el.id = 'prev-slide-area';
+  el.addEventListener('click', prevSlide, false);
+  document.querySelector('section.slides').appendChild(el);
+
+  var el = document.createElement('div');
+  el.className = 'slide-area';
+  el.id = 'next-slide-area';
+  el.addEventListener('click', nextSlide, false);
+  document.querySelector('section.slides').appendChild(el);
+
+  /* Swiping */
+
+  document.body.addEventListener('touchstart', handleTouchStart, false);
+}
+
+/* Hash functions */
+
+function getCurSlideFromHash() {
+  var slideNo = parseInt(location.hash.substr(1));
+
+  if (slideNo) {
+    curSlide = slideNo - 1;
+  } else {
+    curSlide = 0;
+  }
+};
+
+function updateHash() {
+  location.replace('#' + (curSlide + 1));
+};
+
+/* Event listeners */
+
+function handleBodyKeyDown(event) {
+  // If we're in a code element, only handle pgup/down.
+  var inCode = event.target.classList.contains('code');
+
+  switch (event.keyCode) {
+    case 78: // 'N' opens presenter notes window
+      if (!inCode && notesEnabled) toggleNotesWindow();
+      break;
+    case 72: // 'H' hides the help text
+    case 27: // escape key
+      if (!inCode) hideHelpText();
+      break;
+
+    case 39: // right arrow
+    case 13: // Enter
+    case 32: // space
+      if (inCode) break;
+    case 34: // PgDn
+      nextSlide();
+      event.preventDefault();
+      break;
+
+    case 37: // left arrow
+    case 8: // Backspace
+      if (inCode) break;
+    case 33: // PgUp
+      prevSlide();
+      event.preventDefault();
+      break;
+
+    case 40: // down arrow
+      if (inCode) break;
+      nextSlide();
+      event.preventDefault();
+      break;
+
+    case 38: // up arrow
+      if (inCode) break;
+      prevSlide();
+      event.preventDefault();
+      break;
+  }
+};
+
+function scaleSmallViewports() {
+  var el = document.querySelector('.slides');
+  var transform = '';
+  var sWidthPx = 1250;
+  var sHeightPx = 750;
+  var sAspectRatio = sWidthPx / sHeightPx;
+  var wAspectRatio = window.innerWidth / window.innerHeight;
+
+  if (wAspectRatio <= sAspectRatio && window.innerWidth < sWidthPx) {
+    transform = 'scale(' + window.innerWidth / sWidthPx + ')';
+  } else if (window.innerHeight < sHeightPx) {
+    transform = 'scale(' + window.innerHeight / sHeightPx + ')';
+  }
+  el.style.transform = transform;
+}
+
+function addEventListeners() {
+  document.addEventListener('keydown', handleBodyKeyDown, false);
+  var resizeTimeout;
+  window.addEventListener('resize', function() {
+    // throttle resize events
+    window.clearTimeout(resizeTimeout);
+    resizeTimeout = window.setTimeout(function() {
+      resizeTimeout = null;
+      scaleSmallViewports();
+    }, 50);
+  });
+}
+
+/* Initialization */
+
+function addFontStyle() {
+  var el = document.createElement('link');
+  el.rel = 'stylesheet';
+  el.type = 'text/css';
+  el.href = '//fonts.googleapis.com/css?family=' +
+            'Open+Sans:regular,semibold,italic,italicsemibold|Droid+Sans+Mono';
+
+  document.body.appendChild(el);
+};
+
+function addGeneralStyle() {
+  var el = document.createElement('link');
+  el.rel = 'stylesheet';
+  el.type = 'text/css';
+  el.href = PERMANENT_URL_PREFIX + 'styles.css';
+  document.body.appendChild(el);
+
+  var el = document.createElement('meta');
+  el.name = 'viewport';
+  el.content = 'width=device-width,height=device-height,initial-scale=1';
+  document.querySelector('head').appendChild(el);
+
+  var el = document.createElement('meta');
+  el.name = 'apple-mobile-web-app-capable';
+  el.content = 'yes';
+  document.querySelector('head').appendChild(el);
+
+  scaleSmallViewports();
+};
+
+function handleDomLoaded() {
+  slideEls = document.querySelectorAll('section.slides > article');
+
+  setupFrames();
+
+  addFontStyle();
+  addGeneralStyle();
+  addEventListeners();
+
+  updateSlides();
+
+  setupInteraction();
+
+  if (window.location.hostname == 'localhost' || window.location.hostname == '127.0.0.1' || window.location.hostname == '::1') {
+    hideHelpText();
+  }
+
+  document.body.classList.add('loaded');
+
+  setupNotesSync();
+};
+
+function initialize() {
+  getCurSlideFromHash();
+
+  if (window['_DEBUG']) {
+    PERMANENT_URL_PREFIX = '../';
+  }
+
+  if (window['_DCL']) {
+    handleDomLoaded();
+  } else {
+    document.addEventListener('DOMContentLoaded', handleDomLoaded, false);
+  }
+}
+
+// If ?debug exists then load the script relative instead of absolute
+if (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) {
+  document.addEventListener('DOMContentLoaded', function() {
+    // Avoid missing the DomContentLoaded event
+    window['_DCL'] = true
+  }, false);
+
+  window['_DEBUG'] = true;
+  var script = document.createElement('script');
+  script.type = 'text/javascript';
+  script.src = '../slides.js';
+  var s = document.getElementsByTagName('script')[0];
+  s.parentNode.insertBefore(script, s);
+
+  // Remove this script
+  s.parentNode.removeChild(s);
+} else {
+  initialize();
+}
+
+/* Synchronize windows when notes are enabled */
+
+function setupNotesSync() {
+  if (!notesEnabled) return;
+
+  function setupPlayResizeSync() {
+    var out = document.getElementsByClassName('output');
+    for (var i = 0; i < out.length; i++) {
+      $(out[i]).bind('resize', function(event) {
+        if ($(event.target).hasClass('ui-resizable')) {
+          localStorage.setItem('play-index', i);
+          localStorage.setItem('output-style', out[i].style.cssText);
+        }
+      })
+    }
+  };
+  function setupPlayCodeSync() {
+    var play = document.querySelectorAll('div.playground');
+    for (var i = 0; i < play.length; i++) {
+      play[i].addEventListener('input', inputHandler, false);
+
+      function inputHandler(e) {
+        localStorage.setItem('play-index', i);
+        localStorage.setItem('play-code', e.target.innerHTML);
+      }
+    }
+  };
+
+  setupPlayCodeSync();
+  setupPlayResizeSync();
+  localStorage.setItem('destSlide', curSlide);
+  window.addEventListener('storage', updateOtherWindow, false);
+}
+
+// An update to local storage is caught only by the other window
+// The triggering window does not handle any sync actions
+function updateOtherWindow(e) {
+  // Ignore remove storage events which are not meant to update the other window
+  var isRemoveStorageEvent = !e.newValue;
+  if (isRemoveStorageEvent) return;
+
+  var destSlide = localStorage.getItem('destSlide');
+  while (destSlide > curSlide) {
+    nextSlide();
+  }
+  while (destSlide < curSlide) {
+    prevSlide();
+  }
+
+  updatePlay(e);
+  updateNotes();
+}
diff --git a/2018/10/22/ocjdbc/ocjdbc_files/styles.css b/2018/10/22/ocjdbc/ocjdbc_files/styles.css
new file mode 100644
index 0000000..d9590be
--- /dev/null
+++ b/2018/10/22/ocjdbc/ocjdbc_files/styles.css
@@ -0,0 +1,540 @@
+@media screen {
+  /* Framework */
+  html {
+    height: 100%;
+  }
+
+  body {
+    margin: 0;
+    padding: 0;
+
+    display: block !important;
+
+    height: 100%;
+    height: 100vh;
+
+    overflow: hidden;
+
+    background: rgb(215, 215, 215);
+    background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
+    background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
+    background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
+    background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(rgb(240, 240, 240)), to(rgb(190, 190, 190)));
+
+    -webkit-font-smoothing: antialiased;
+  }
+
+  .slides {
+    width: 100%;
+    height: 100%;
+    left: 0;
+    top: 0;
+
+    position: absolute;
+
+    -webkit-transform: translate3d(0, 0, 0);
+  }
+
+  .slides > article {
+    display: block;
+
+    position: absolute;
+    overflow: hidden;
+
+    width: 900px;
+    height: 700px;
+
+    left: 50%;
+    top: 50%;
+
+    margin-left: -450px;
+    margin-top: -350px;
+
+    padding: 40px 60px;
+
+    box-sizing: border-box;
+    -o-box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+
+    border-radius: 10px;
+    -o-border-radius: 10px;
+    -moz-border-radius: 10px;
+    -webkit-border-radius: 10px;
+
+    background-color: white;
+
+    border: 1px solid rgba(0, 0, 0, .3);
+
+    transition: transform .3s ease-out;
+    -o-transition: -o-transform .3s ease-out;
+    -moz-transition: -moz-transform .3s ease-out;
+    -webkit-transition: -webkit-transform .3s ease-out;
+  }
+  .slides.layout-widescreen > article {
+    margin-left: -550px;
+    width: 1100px;
+  }
+  .slides.layout-faux-widescreen > article {
+    margin-left: -550px;
+    width: 1100px;
+
+    padding: 40px 160px;
+  }
+
+  .slides.layout-widescreen > article:not(.nobackground):not(.biglogo),
+  .slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) {
+    background-position-x: 0, 840px;
+  }
+
+  /* Clickable/tappable areas */
+
+  .slide-area {
+    z-index: 1000;
+
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 150px;
+    height: 700px;
+
+    left: 50%;
+    top: 50%;
+
+    cursor: pointer;
+    margin-top: -350px;
+
+    tap-highlight-color: transparent;
+    -o-tap-highlight-color: transparent;
+    -moz-tap-highlight-color: transparent;
+    -webkit-tap-highlight-color: transparent;
+  }
+  #prev-slide-area {
+    margin-left: -550px;
+  }
+  #next-slide-area {
+    margin-left: 400px;
+  }
+  .slides.layout-widescreen #prev-slide-area,
+  .slides.layout-faux-widescreen #prev-slide-area {
+    margin-left: -650px;
+  }
+  .slides.layout-widescreen #next-slide-area,
+  .slides.layout-faux-widescreen #next-slide-area {
+    margin-left: 500px;
+  }
+
+  /* Slides */
+
+  .slides > article {
+    display: none;
+  }
+  .slides > article.far-past {
+    display: block;
+    transform: translate(-2040px);
+    -o-transform: translate(-2040px);
+    -moz-transform: translate(-2040px);
+    -webkit-transform: translate3d(-2040px, 0, 0);
+  }
+  .slides > article.past {
+    display: block;
+    transform: translate(-1020px);
+    -o-transform: translate(-1020px);
+    -moz-transform: translate(-1020px);
+    -webkit-transform: translate3d(-1020px, 0, 0);
+  }
+  .slides > article.current {
+    display: block;
+    transform: translate(0);
+    -o-transform: translate(0);
+    -moz-transform: translate(0);
+    -webkit-transform: translate3d(0, 0, 0);
+  }
+  .slides > article.next {
+    display: block;
+    transform: translate(1020px);
+    -o-transform: translate(1020px);
+    -moz-transform: translate(1020px);
+    -webkit-transform: translate3d(1020px, 0, 0);
+  }
+  .slides > article.far-next {
+    display: block;
+    transform: translate(2040px);
+    -o-transform: translate(2040px);
+    -moz-transform: translate(2040px);
+    -webkit-transform: translate3d(2040px, 0, 0);
+  }
+
+  .slides.layout-widescreen > article.far-past,
+  .slides.layout-faux-widescreen > article.far-past {
+    display: block;
+    transform: translate(-2260px);
+    -o-transform: translate(-2260px);
+    -moz-transform: translate(-2260px);
+    -webkit-transform: translate3d(-2260px, 0, 0);
+  }
+  .slides.layout-widescreen > article.past,
+  .slides.layout-faux-widescreen > article.past {
+    display: block;
+    transform: translate(-1130px);
+    -o-transform: translate(-1130px);
+    -moz-transform: translate(-1130px);
+    -webkit-transform: translate3d(-1130px, 0, 0);
+  }
+  .slides.layout-widescreen > article.current,
+  .slides.layout-faux-widescreen > article.current {
+    display: block;
+    transform: translate(0);
+    -o-transform: translate(0);
+    -moz-transform: translate(0);
+    -webkit-transform: translate3d(0, 0, 0);
+  }
+  .slides.layout-widescreen > article.next,
+  .slides.layout-faux-widescreen > article.next {
+    display: block;
+    transform: translate(1130px);
+    -o-transform: translate(1130px);
+    -moz-transform: translate(1130px);
+    -webkit-transform: translate3d(1130px, 0, 0);
+  }
+  .slides.layout-widescreen > article.far-next,
+  .slides.layout-faux-widescreen > article.far-next {
+    display: block;
+    transform: translate(2260px);
+    -o-transform: translate(2260px);
+    -moz-transform: translate(2260px);
+    -webkit-transform: translate3d(2260px, 0, 0);
+  }
+}
+
+@media print {
+  /* Set page layout */
+  @page {
+    size: A4 landscape;
+  }
+
+  body {
+    display: block !important;
+  }
+
+  .slides > article {
+    display: block;
+
+    position: relative;
+
+    page-break-inside: never;
+    page-break-after: always;
+
+    overflow: hidden;
+  }
+
+  h2 {
+    position: static !important;
+    margin-top: 400px !important;
+    margin-bottom: 100px !important;
+  }
+
+  div.code {
+    background: rgb(240, 240, 240);
+  }
+
+  /* Add explicit links */
+  a:link:after, a:visited:after {
+   content: " (" attr(href) ") ";
+   font-size: 50%;
+  }
+
+  #help {
+    display: none;
+    visibility: hidden;
+  }
+}
+
+/* Styles for full screen mode */
+.slides.fullscreen > article.next, .slides.fullscreen > article.far-next,
+.slides.fullscreen > article.past, .slides.fullscreen > article.far-past {
+  display: none;
+}
+
+/* Styles for slides */
+
+.slides > article {
+  font-family: 'Open Sans', Arial, sans-serif;
+
+  color: black;
+  text-shadow: 0 1px 1px rgba(0, 0, 0, .1);
+
+  font-size: 26px;
+  line-height: 36px;
+
+  letter-spacing: -1px;
+}
+
+b {
+  font-weight: 600;
+}
+
+a {
+  color: rgb(0, 102, 204);
+  text-decoration: none;
+}
+a:visited {
+  color: rgba(0, 102, 204, .75);
+}
+a:hover {
+  color: black;
+}
+
+p {
+  margin: 0;
+  padding: 0;
+
+  margin-top: 20px;
+}
+p:first-child {
+  margin-top: 0;
+}
+
+h1 {
+  font-size: 60px;
+  line-height: 60px;
+
+  padding: 0;
+  margin: 0;
+  margin-top: 200px;
+  margin-bottom: 5px;
+  padding-right: 40px;
+
+  font-weight: 600;
+
+  letter-spacing: -3px;
+
+  color: rgb(51, 51, 51);
+}
+
+h2 {
+  font-size: 45px;
+  line-height: 45px;
+
+  position: absolute;
+  bottom: 150px;
+
+  padding: 0;
+  margin: 0;
+  padding-right: 40px;
+
+  font-weight: 600;
+
+  letter-spacing: -2px;
+
+  color: rgb(51, 51, 51);
+}
+
+h3 {
+  font-size: 30px;
+  line-height: 36px;
+
+  padding: 0;
+  margin: 0;
+  padding-right: 40px;
+
+  font-weight: 600;
+
+  letter-spacing: -1px;
+
+  color: rgb(51, 51, 51);
+}
+
+ul {
+  margin: 0;
+  padding: 0;
+  margin-top: 20px;
+  margin-left: 1.5em;
+}
+li {
+  padding: 0;
+  margin: 0 0 .5em 0;
+}
+
+div.code {
+  padding: 5px 10px;
+  margin-top: 20px;
+  margin-bottom: 20px;
+  overflow: hidden;
+
+  background: rgb(240, 240, 240);
+  border: 1px solid rgb(224, 224, 224);
+}
+pre {
+  margin: 0;
+  padding: 0;
+
+  font-family: 'Droid Sans Mono', 'Courier New', monospace;
+  font-size: 18px;
+  line-height: 24px;
+  letter-spacing: -1px;
+
+  color: black;
+}
+
+pre.numbers span:before {
+  content: attr(num);
+  margin-right: 1em;
+  display: inline-block;
+}
+
+code {
+  font-size: 95%;
+  font-family: 'Droid Sans Mono', 'Courier New', monospace;
+
+  color: black;
+}
+
+article > .image,
+article > .video {
+  text-align: center;
+  margin-top: 40px;
+}
+
+article.background {
+  background-size: contain;
+  background-repeat: round;
+}
+
+table {
+  width: 100%;
+  border-collapse: collapse;
+  margin-top: 40px;
+}
+th {
+  font-weight: 600;
+  text-align: left;
+}
+td,
+th {
+  border: 1px solid rgb(224, 224, 224);
+  padding: 5px 10px;
+  vertical-align: top;
+}
+
+p.link {
+  margin-left: 20px;
+}
+
+/* Code */
+div.code {
+  outline: 0px solid transparent;
+}
+div.playground {
+  position: relative;
+}
+div.output {
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  right: 40px;
+  bottom: 40px;
+  background: #202020;
+  padding: 5px 10px;
+  z-index: 2;
+
+  border-radius: 10px;
+  -o-border-radius: 10px;
+  -moz-border-radius: 10px;
+  -webkit-border-radius: 10px;
+
+}
+div.output pre {
+  margin: 0;
+  padding: 0;
+  background: none;
+  border: none;
+  width: 100%;
+  height: 100%;
+  overflow: auto;
+}
+div.output .stdout, div.output pre {
+  color: #e6e6e6;
+}
+div.output .stderr, div.output .error {
+  color: rgb(255, 200, 200);
+}
+div.output .system, div.output .exit {
+  color: rgb(255, 230, 120)
+}
+.buttons {
+  position: relative;
+  float: right;
+  top: -60px;
+  right: 10px;
+}
+div.output .buttons {
+  position: absolute;
+  float: none;
+  top: auto;
+  right: 5px;
+  bottom: 5px;
+}
+
+/* Presenter details */
+.presenter {
+  margin-top: 20px;
+}
+.presenter p,
+.presenter .link {
+  margin: 0;
+  font-size: 28px;
+  line-height: 1.2em;
+}
+
+/* Output resize details */
+.ui-resizable-handle {
+  position: absolute;
+}
+.ui-resizable-n {
+  cursor: n-resize;
+  height: 7px;
+  width: 100%;
+  top: -5px;
+  left: 0;
+}
+.ui-resizable-w {
+  cursor: w-resize;
+  width: 7px;
+  left: -5px;
+  top: 0;
+  height: 100%;
+}
+.ui-resizable-nw {
+  cursor: nw-resize;
+  width: 9px;
+  height: 9px;
+  left: -5px;
+  top: -5px;
+}
+iframe {
+  border: none;
+}
+figcaption {
+  color: #666;
+  text-align: center;
+  font-size: 0.75em;
+}
+
+#help {
+  font-family: 'Open Sans', Arial, sans-serif;
+  text-align: center;
+  color: white;
+  background: #000;
+  opacity: 0.5;
+  position: fixed;
+  bottom: 25px;
+  left: 50px;
+  right: 50px;
+  padding: 20px;
+
+  border-radius: 10px;
+  -o-border-radius: 10px;
+  -moz-border-radius: 10px;
+  -webkit-border-radius: 10px;
+}
diff --git a/2018/10/22/ocjdbc/talk.slide b/2018/10/22/ocjdbc/talk.slide
new file mode 100644
index 0000000..3f0c06a
--- /dev/null
+++ b/2018/10/22/ocjdbc/talk.slide
@@ -0,0 +1,86 @@
+ocjdbc
+OpenCensus + JDBC
+22 Oct 2018
+Tags: java, jdbc, database, opencensus, observability, distributed-tracing, metrics, drivers
+
+Emmanuel T Odeke
+Orijtech, Inc.
+
+* ocjdbc
+
+* What is it?
+- Type 4 Java driver wrapper for the Java Database Connectivity API
+- instrumented for distributed tracing and metrics with OpenCensus
+- OpenCensus(oc) + JDBC(jdbc) = ocjdbc
+.image ocjdbc.png 400 _
+
+* About OpenCensus
+- OpenCensus is a vendor agnostic single distribution of libraries for distributed tracing and metrics
+- The work of a collective, talented and vibrant community
+- Entirely open sourced rewrite of the observability systems that have powered Google's production systems for the past 10+ years
+- Collect metrics and traces once, export to backends of your choice
+- Exporters/backends include: AWS X-Ray, Google Stackdriver, SignalFx, Zipkin, Jaeger, Datadog, Prometheus, Honeycomb
+- zPages for live introspection
+- For microservices and monoliths alike!
+- Implemented in C#, C++, Go, Java, Python, Node.js, PHP, Ruby
+- Website: [[https://opencensus.io/][https://opencensus.io/]]
+- Github: [[https://github.com/census-instrumentation][https://github.com/census-instrumentation]]
+
+* Observability for your JDBC using apps
+
+* Update your pom.xml file
+.code maven.xml
+
+* Source code update
+- Just wrap your connection
+.code import.java
+
+* Now enable exporters to extract your traces and metrics
+- Pick any of the [[https://opencensus.io/guides/exporters/supported-exporters/java/][Java trace and metrics exporters]]
+.code exporters.java
+
+* Results
+
+* Traces
+
+* All traces
+- Navigate to the trace backend's UI
+.image ocjdbc-tracing-all.png 500 _
+
+* Individual trace
+.image ocjdbc-tracing-single-without-sql.png 500 _
+
+* Individual trace with SQL annotation enabled 
+- PII risk so passed as an option
+.code conn_with_annotation.java
+.image ocjdbc-tracing-single-with-sql.png 320 _
+
+* Metrics
+
+* Recorded metrics
+- Latency in milliseconds
+- Number of calls
+- Tags include: "method", "status", "error"
+- Important to identify bottlenecks, slow queries, hotspots in your system
+- Use them to automatically alert your teams and SREs if latency increases beyond a threshold, error rates etc
+
+* All metrics
+.image ocjdbc-metrics-all.png 600 _
+
+* Calls
+.image ocjdbc-metrics-calls.png 580 _
+
+* Latency buckets
+.image ocjdbc-metrics-latency-bucket.png 560 _
+
+* Appreciation
+Great thanks for the collaboration and support from:
+- Yang Song
+- Bogdan Drutu
+- Pritam Shah
+- The entire OpenCensus community and ecosystem
+
+* Resources
+- Please try out the runnable code at [[https://opencensus.io/guides/integrations/sql/java_sql][https://opencensus.io/guides/integrations/sql/java_sql]]
+- OpenCensus project's website [[https://opencensus.io][https://opencensus.io]]
+- OpenCensus Gitter room [[https://gitter.im/census-instrumentation/Lobby][https://gitter.im/census-instrumentation/Lobby]]
diff --git a/2020/12/03/gosystemsconf/fnichs.htm b/2020/12/03/gosystemsconf/gosystemsconf.htm
similarity index 95%
rename from 2020/12/03/gosystemsconf/fnichs.htm
rename to 2020/12/03/gosystemsconf/gosystemsconf.htm
index 6934b7b..f7aac66 100644
--- a/2020/12/03/gosystemsconf/fnichs.htm
+++ b/2020/12/03/gosystemsconf/gosystemsconf.htm
@@ -6,7 +6,7 @@
     
-    
+    
 
     
 
@@ -79,7 +79,7 @@ 

About myself

Simple photo upload microservice

-
+
3
@@ -89,7 +89,7 @@

Simple photo upload microservice

Uber: microservices graph from July 2020 blog post

-
+
4
@@ -99,7 +99,7 @@

Uber: microservices graph from July 2020 blog post

Netflix: 2014 Bruce Wong presentation

-
+
5
@@ -109,7 +109,7 @@

Netflix: 2014 Bruce Wong presentation

Netflix: 2016 Josh Evans presentation

-
+
6
@@ -270,7 +270,7 @@

Thanksgiving 2018 with Dgraph

-
+
13 @@ -281,7 +281,7 @@

Thanksgiving 2018 with Dgraph

Later happiness and testimonial

Manish's tweet https://twitter.com/manishrjain/status/1090041366380302336

-
+
14 @@ -343,7 +343,7 @@

Tracing & Metrics

-
+
17 @@ -356,7 +356,7 @@

Tracing aftermath

  • Result I presented
-
+
18 @@ -369,7 +369,7 @@

Metrics aftermath

  • Result I presented
-
+
19 @@ -489,7 +489,7 @@

3 sigma rule

-
+
24 @@ -712,7 +712,7 @@

CPU Profiling

CPU Profiling result

-
+
33
@@ -790,7 +790,7 @@

Memory Profiling

Memory Profiling result

-
+
36
@@ -863,6 +863,7 @@

References

  • Bryan C Mills 2019: runtime: "program exceeds 50-thread limit"
  • OpenCensus
  • OpenTelemetry
  • +
  • Antifragile: Nassim Taleb 2014
  • @@ -907,7 +908,7 @@

    Thank you

    - + - \ No newline at end of file + \ No newline at end of file diff --git a/2020/12/03/gosystemsconf/gosystemsconf.slide b/2020/12/03/gosystemsconf/gosystemsconf.slide index 5c0e58a..f679c56 100644 --- a/2020/12/03/gosystemsconf/gosystemsconf.slide +++ b/2020/12/03/gosystemsconf/gosystemsconf.slide @@ -317,3 +317,4 @@ go tool pprof http://localhost:3338/debug/pprof/heap?seconds=30 - [Bryan C Mills 2019: runtime: "program exceeds 50-thread limit"](https://github.com/golang/go/issues/32326/) - [OpenCensus](https://opencensus.io/) - [OpenTelemetry](https://opentelemetry.io/) +- [Antifragile: Nassim Taleb 2014](https://www.amazon.com/Antifragile-Things-That-Disorder-Incerto/dp/0812979680/) diff --git a/2020/12/03/gosystemsconf/fnichs_files/css b/2020/12/03/gosystemsconf/gosystemsconf_files/css similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/css rename to 2020/12/03/gosystemsconf/gosystemsconf_files/css diff --git a/2020/12/03/gosystemsconf/fnichs_files/dgraph-thanksgiving.png b/2020/12/03/gosystemsconf/gosystemsconf_files/dgraph-thanksgiving.png similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/dgraph-thanksgiving.png rename to 2020/12/03/gosystemsconf/gosystemsconf_files/dgraph-thanksgiving.png diff --git a/2020/12/03/gosystemsconf/fnichs_files/manish-needle-tweet.png b/2020/12/03/gosystemsconf/gosystemsconf_files/manish-needle-tweet.png similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/manish-needle-tweet.png rename to 2020/12/03/gosystemsconf/gosystemsconf_files/manish-needle-tweet.png diff --git a/2020/12/03/gosystemsconf/fnichs_files/mapbox-search-metrics.png b/2020/12/03/gosystemsconf/gosystemsconf_files/mapbox-search-metrics.png similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/mapbox-search-metrics.png rename to 2020/12/03/gosystemsconf/gosystemsconf_files/mapbox-search-metrics.png diff --git a/2020/12/03/gosystemsconf/fnichs_files/mapbox-search-traces.png b/2020/12/03/gosystemsconf/gosystemsconf_files/mapbox-search-traces.png similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/mapbox-search-traces.png rename to 2020/12/03/gosystemsconf/gosystemsconf_files/mapbox-search-traces.png diff --git a/2020/12/03/gosystemsconf/fnichs_files/mapbox-search.jpeg b/2020/12/03/gosystemsconf/gosystemsconf_files/mapbox-search.jpeg similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/mapbox-search.jpeg rename to 2020/12/03/gosystemsconf/gosystemsconf_files/mapbox-search.jpeg diff --git a/2020/12/03/gosystemsconf/fnichs_files/netflix-microservices-2014.jpg b/2020/12/03/gosystemsconf/gosystemsconf_files/netflix-microservices-2014.jpg similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/netflix-microservices-2014.jpg rename to 2020/12/03/gosystemsconf/gosystemsconf_files/netflix-microservices-2014.jpg diff --git a/2020/12/03/gosystemsconf/fnichs_files/netflix-microservices-mastering-chaos.png b/2020/12/03/gosystemsconf/gosystemsconf_files/netflix-microservices-mastering-chaos.png similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/netflix-microservices-mastering-chaos.png rename to 2020/12/03/gosystemsconf/gosystemsconf_files/netflix-microservices-mastering-chaos.png diff --git a/2020/12/03/gosystemsconf/fnichs_files/normal-distribution-formula.png b/2020/12/03/gosystemsconf/gosystemsconf_files/normal-distribution-formula.png similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/normal-distribution-formula.png rename to 2020/12/03/gosystemsconf/gosystemsconf_files/normal-distribution-formula.png diff --git a/2020/12/03/gosystemsconf/fnichs_files/parsecoin-profile-cpu.png b/2020/12/03/gosystemsconf/gosystemsconf_files/parsecoin-profile-cpu.png similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/parsecoin-profile-cpu.png rename to 2020/12/03/gosystemsconf/gosystemsconf_files/parsecoin-profile-cpu.png diff --git a/2020/12/03/gosystemsconf/fnichs_files/parsecoin-profile-mem.png b/2020/12/03/gosystemsconf/gosystemsconf_files/parsecoin-profile-mem.png similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/parsecoin-profile-mem.png rename to 2020/12/03/gosystemsconf/gosystemsconf_files/parsecoin-profile-mem.png diff --git a/2020/12/03/gosystemsconf/fnichs_files/play.js b/2020/12/03/gosystemsconf/gosystemsconf_files/play.js similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/play.js rename to 2020/12/03/gosystemsconf/gosystemsconf_files/play.js diff --git a/2020/12/03/gosystemsconf/fnichs_files/simple-photo-upload.jpg b/2020/12/03/gosystemsconf/gosystemsconf_files/simple-photo-upload.jpg similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/simple-photo-upload.jpg rename to 2020/12/03/gosystemsconf/gosystemsconf_files/simple-photo-upload.jpg diff --git a/2020/12/03/gosystemsconf/fnichs_files/slides.js b/2020/12/03/gosystemsconf/gosystemsconf_files/slides.js similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/slides.js rename to 2020/12/03/gosystemsconf/gosystemsconf_files/slides.js diff --git a/2020/12/03/gosystemsconf/fnichs_files/styles.css b/2020/12/03/gosystemsconf/gosystemsconf_files/styles.css similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/styles.css rename to 2020/12/03/gosystemsconf/gosystemsconf_files/styles.css diff --git a/2020/12/03/gosystemsconf/fnichs_files/uber-microservices.png b/2020/12/03/gosystemsconf/gosystemsconf_files/uber-microservices.png similarity index 100% rename from 2020/12/03/gosystemsconf/fnichs_files/uber-microservices.png rename to 2020/12/03/gosystemsconf/gosystemsconf_files/uber-microservices.png diff --git a/2021/04/15/google/CloudSpannerSafari.html b/2021/04/15/google/CloudSpannerSafari.html new file mode 100644 index 0000000..da648fa --- /dev/null +++ b/2021/04/15/google/CloudSpannerSafari.html @@ -0,0 +1,925 @@ + + + + Cloud Spanner Safari + + + + + + + + + + + +
    + +
    +

    Cloud Spanner Safari

    +

    A journey from the outside, into Cloud Spanner's underbelly

    +

    15 April 2021

    + +
    + + +

    + Emmanuel T Odeke +

    + + + +

    + Orijtech, Inc. +

    + + +
    + +
    + + + +
    + +

    Journey from outside, to the inside

    +
    + + 2 +
    + + + +
    + +

    About myself

    +
      +
    • Emmanuel T Odeke
    • +
    • Building Orijtech, Inc
    • +
    • Friend of Google: Contributor, Supplier, Google Cloud Partner for many years
    • +
    • Help build many systems, projects, and work with a bunch of you
    • +
    • Avid open source producer and consumer
    • +
    • Designed and built Cloud Spanner for Django, Cloud Spanner for Ruby-on-Rails/ActiveRecord
    • +
    • Led OpenCensus observability in many aspects from zero to successful merger
    • +
    • Core contributor to the Go programming language
    • +
    • Always learning, and enjoy solving problems!
    • +
    + + + 3 +
    + + + +
    + +

    What is this talk about?

    +
      +
    • Dealt with Cloud Spanner's underbelly from the outside world
    • +
    • Hinderances towards building with, and adopting Cloud Spanner
    • +
    • Suggestions on how to grow
    • +
    • Reality check
    • +
    • Advisory and ideas for how to act upon identified needs
    • +
    + + + 4 +
    + + + +
    + +

    Narrative

    +
      +
    • Cloud Spanner is Google's distributed relational, cloud native database, indefinitely scalable, highly performant, managed, battle tested
    • +
    • Highest availability defying normal expectations of the CAP theorem
    • +
    • Majority of the world uses legacy systems, mostly maintains code
    • +
    • To grow Cloud Spanner, we need more and newer businesses to switch over
    • +
    • To enable adoption, seemlessly integrate with existing code, reduce learning curve
    • +
    • MARR (Minimum Acceptable Rate of Return) of using new databases must be much higher and sustainable, than just using older stable systems
    • +
    • Switching over to any new database requires experience, determinism, features
    • +
    • Knowledge gaps
    • +
    + + + 5 +
    + + + +
    + +

    Market share

    + + 6 +
    + + + + + + + +
    + +

    Status quo

    +
      +
    • At the top, we have OracleDB(42yr), MySQL(26yr), Microsoft SQL Server(32yr), PostgreSQL(25yr), IBM Db2(38yr), SQLite(30yr)
    • +
    • Cloud Spanner was released February 2017
    • +
    • Doing great for a very young database
    • +
    • To get to the top, plumb with both new and legacy systems, frameworks
    • +
    • Make switch-over trivial
    • +
    • Convenience, so that engineers can trivially convince their engineering management and finance departments to move to Cloud Spanner
    • +
    • Cloud Spanner can definitely make it to Number 1!
    • +
    + + + 8 +
    + + + +
    + +

    Status quo

    +
      +
    • Incumbents have dominated
    • +
    • Scaling databases and reliability are pretty much rocket science
    • +
    • Information and skills in this industry are very scarce
    • +
    • Sugu Sougoumarane, CTO/co-founder of PlanetScale Data scaled YouTube's MySQL; was hired by Elon Musk for X.com, Paypal
    • +
    • Can't expect every company to afford ninja dBAs and SRE teams
    • +
    • Most applications are built using frameworks, ORMs: Django, Ruby-on-Rails, Spring
    • +
    • Most code is maintained, more than newly written; hard to justify rewriting legacy code that works
    • +
    • Dialect expertise means job pool is very limited in the already limited engineering talent pool
    • +
    • Betting your business on a technology requires evidence of extraordinary results, incumbent mass adoption, buzz, leadership, copying from successes
    • +
    + + + 9 +
    + + + +
    + +

    Constraints for most companies

    +
      +
    • Proof of concepts evolve into fully fledged products -- engineering decisions and stack have to be good from the start
    • +
    • Technical expertise to run and scale databases
    • +
    • Monetary constraints
    • +
    • SRE problems
    • +
    • Lack of expertise
    • +
    • Every penny counts
    • +
    • Least time, cost to setup/use -> creates more trust and easy decision making
    • +
    • Simplicity is much better
    • +
    + + + 10 +
    + + + +
    + +

    Cloud Spanner as a business

    + + 11 +
    + + + +
    + +

    Cloud Spanner strengths

    +
      +
    • Engineering prowess, brand, and powerful backing of Google
    • +
    • Amazing leadership and teams: genuinely focused on solving customer problems
    • +
    • Cloud Spanner removes the need to become a dBA, or a scaling expert!
    • +
    • Guts cost of running own databases: SRE nightmares, knowledge blackholes, server cost, observability, availability problems
    • +
    • Scalability, libraries, integrations
    • +
    • Very nice APIs to insert or update, named variables in statements, running transactions
    • +
    • Very nice UI that's multi-purpose
    • +
    • Backing of a top 3 cloud, and eco-system of other cloud products
    • +
    • Cloud Spanner emulator introduced in mid 2020, allows for trials
    • +
    • Ability to run on 1 node reduces cost massively, attractive to companies of all sizes
    • +
    + + + 12 +
    + + + +
    + +

    Increasing market share

    +
      +
    • Google is successful for wholely owning information retrieval, making it trivial for every single business to find information and advertise their businesses
    • +
    • Tackle the status quo and go into markets for which re-writing code afresh is impossible
    • +
    • Analysis of the market: we listed out top ORMs by popularity
    • +
    • Target: make Cloud Spanner trivially usable on popular ORMs
    • +
    • Prior attempts at integrating with Rails and Django had failed as far as I know
    • +
    + + + 13 +
    + + + + + + + + + + + +
    + +

    Moonshots

    + + 16 +
    + + + +
    + +

    Moonshots

    +
      +
    • Audacious goals
    • +
    • Meet businesses at home, bring Cloud Spanner to them
    • +
    • Exisiting and future customers who'll feed into Google Cloud Platform
    • +
    • Engineering leadership: Pritam, Shanika, Vikram, and others reached out, we collaborated
    • +
    +
    + + 17 +
    + + + +
    + +

    Journey

    + + 18 +
    + + + +
    + +

    Gestalt switch

    +
    + + 19 +
    + + + +
    + +

    Lack of AUTO*INCREMENT

    +
      +
    • Most of the world for the past 30 years has been using SQL databases that support AUTO*INCREMENT
    • +
    • Sure, it is to avoid hot spotting in Cloud Spanner but patching to support for UUID generation was a whole hassle
    • +
    • Patched support means customers have to re-write their sorting, breaks results: Hyrum's Law
    • +
    • Cloud Spanner could have a mapping between assigned IDs and the actual UUIDs used as PRIMARY KEY
    • +
    • Provide perhaps a UUID function that's used with DDL
    • +
    + + + 20 +
    + + + +
    + +

    Columns starting with "_" are not supported

    +
      +
    • Makes it impossible for ORMs and frameworks to have special ordering/sorting routines nor orderings
    • +
    • Django has _order but unfortunately can't be supported with Cloud Spanner
    • +
    + + + 21 +
    + + + +
    + +

    Lack of NUMERIC data type then

    +
      +
    • The NUMERIC data type was added in late September 2020 (7 months ago)
    • +
    • The remedy for this was just to store big nums as strings to avoid precision loss
    • +
    + + + 22 +
    + + + + + + + + + + + +
    + +

    Hyper improvement with query optimizer

    +
      +
    • Given this DDL
    • +
    +
    CREATE TABLE Span (
    +    id STRING(16) NOT NULL,
    +    trace_id STRING(32) NOT NULL,
    +    parent_id STRING(16),
    +    source_node STRING(32) NOT NULL,
    +    start_time TIMESTAMP NOT NULL,
    +    end_time TIMESTAMP,
    +    saved_at TIMESTAMP OPTIONS (allow_commit_timestamp=true),
    +    name STRING(MAX) NOT NULL,
    +    kind INT64,
    +    status_code INT64,
    +    status_message STRING(MAX),
    +    user_agent STRING(MAX),
    +    CONSTRAINT FK_SpanNode FOREIGN KEY (source_node) REFERENCES Node(id),
    +) PRIMARY KEY (id, trace_id);
    +CREATE INDEX Span_EndTime ON Span (end_time)
    +CREATE INDEX Span_StartTime ON Span (start_time)
    +
    + + + 25 +
    + + + +
    + +

    Query optimizer improvement

    +
    SELECT DISTINCT(name) FROM Span WHERE start_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 120 SECOND)
    +
    +
    + + 26 +
    + + + +
    + +

    Hacky remedy

    +
      +
    • Using FORCE_INDEX
    • +
    • Avoid the full table scan that takes 16+ seconds
    • +
    • Firstly infer that the output table names exist in the full table, else return an error
    • +
    • Search through the target index, retrieve the respective PRIMARY KEY values and then search only by the trimmed value set using ID
    • +
    + + + 27 +
    + + + +
    + +

    Better remedy: more composite index: 16+sec -> 1.89sec

    +
    CREATE INDEX Span_SourceNode_Name_StartTime_EndTime_TraceID 
    +ON Span (
    +    source_node, name, start_time, end_time, trace_id
    +)
    +
    +
    + + 28 +
    + + + +
    + +

    Transactions can't mix DQL with DML

    +
      +
    • Cannot mix Data Query Language (DQL) statements with Data Manipulation Language (DML) statements
    • +
    • SELECT * From Org1; DROP Table Org2
    • +
    • Made migrations insanely slow, can't be parallelized because of strict ordering
    • +
    • Faux transaction whereby only abort DML iff prior DQL failed
    • +
    • While the DQL is happening, can synchronize watches and then perform an exfiltration of data or modify tables concurrently and rename them, so that subsequent DML won't run, then rename it
    • +
    • Ooh, INFORMATION_SCHEMA queries cannot also be performed in a READ-WRITE transaction :-(
    • +
    + + + 29 +
    + + + +
    + +

    Previously no advisory for expensive operations nor observability

    +
      +
    • In March 2018 after brainstorming with Pritam, I wrote an article guiding folks for how to use OpenCensus with Cloud Spanner in Java and Go
    • +
    • It revealed cold start issues with CreateSession, and CreateTransaction, and also Cloud Spanner internally too after I sent a whole bunch of requests and triggered some alarms
    • +
    • Caused a bit of an uproar within internal Spanner engineering, and even ropped in then engineering director Damian Reeves who personally replied and debugged issues
    • +
    • Snap struggled with super high latency and didn't have any reasoning for why, I chimed in with data per google-go-cloud/#207
    • +
    • Why were customers guessing when we've got the most modern tools, and pioneered observability? Dapper, Census, OpenCensus all sparked multi-billion dollar industries
    • +
    • Partly fixed with Troubleshooting app latency with Cloud Spanner and OpenCensus
    • +
    + + + 30 +
    + + + +
    + +

    Column types can't be changed

    +
      +
    • To change a data type, you have to create an entirely new table, transform/migrate all the data, then delete the prior table -- this is very inconvenient and can go on indefinitely, something businesses might get a bitter taste in their mouths about
    • +
    + + + 31 +
    + + + +
    + +

    No support for renaming tables and columns

    +
      +
    • Makes Database schema migrations and renames impossible -- requires an expensive and laborious migration, can leave bitter tastes in one's mouth
    • +
    + + + 32 +
    + + + +
    + +

    Casting DATE to TIMESTAMP unexpectedly adds an hour

    +
      +
    • Helped out by Andrew Byrne, who showed that we should always use "SELECT TIMESTAMP(date_column, 'GMT') FROM TBL"
    • +
    • The solution works for that DATE->TIMESTAMP, but not when the ORM casts between TIMESTAMP->TIMESTAMP given that Cloud Spanner can't type check on field names
    • +
    + + + 33 +
    + + + +
    + +

    Lots of casting to do with IFNULL

    +
      +
    • Lots of boiler plate needed for arithmetic functions when doing additions from dynamically typed languages
    • +
    • Can't easily pass in parameters for addition lest: google.api_core.exceptions.InvalidArgument: 400 Operands of + cannot be literal
    • +
    + + + 34 +
    + + + +
    + +

    Foreign keys lack "ON DELETE CASCADE"

    +
      +
    • Foreign keys were added to Cloud Spanner announced on Thursday 5th March 2020
    • +
    • Unfortunately can't delete related rows when a foreign key is deleted
    • +
    • Can't support most ORMs
    • +
    • Customers have to write their own specialized deletion routines, know which tables are associated
    • +
    • Customers have to learn about using INFORMATION_SCHEMA
    • +
    • Big surprise here, and requires Cloud Spanner expertise, to swap in for table interleaving but that's hacking now
    • +
    • Due to lack of proper support for FOREIGN KEY so can't properly delete per spanner-django/#313, nor for any other ORM
    • +
    + + + 35 +
    + + + +
    + +

    Impossible to compare TIMESTAMP & DATE

    +
      +
    • Unfortunately this crashes queries, despite the ability to use TIMESTAMP(date_column, "GMT")
    • +
    • At query time, the field type is unknown so this is an unsolved problem
    • +
    + + + 36 +
    + + + +
    + +

    Lack of SQL triggers

    +
      +
    • The inability to intercept events due to lack of SQL triggers makes it a problem to react to events that make traditional SQL databases useful
    • +
    • Also a feature that's been used for decades
    • +
    • Perhaps a combination of PubSub + Cloud Functions? Cloud Run?
    • +
    + + + 37 +
    + + + +
    + +

    Inability to directly use Unicode as column names, without quoting values

    +
      +
    • SELECT (1) AS föö, 2 as umläut fails
    • +
    • Seemingly not easily available information on the docs website
    • +
    • Required a pass over every single SQL query to backtick as per spanner-django#374
    • +
    • Had to spend time debugging this failure on my own time
    • +
    + + + 38 +
    + + + +
    + +

    10 second transaction timeouts are impossible to deal with, yet no easy transaction replay

    +
      +
    • While the 10 second timeout is understandable for Cloud Spanner, in the rest of the world without those limits, trying to transfer directly is almost impossible
    • +
    • Had to get my hands dirty and dive into the Python Cloud Spanner API and try to build this
    • +
    • This setup delayed my project by months, and ran over my budget by a lot
    • +
    + + + 39 +
    + + + +
    + +

    Lack of support for proper transaction replay

    +
      +
    • The Cloud Spanner Ruby, Python, Go clients lacked proper transaction replay which uses checksumming to validate replay
    • +
    • Added for python-spanner, but seemingly not for Ruby and Go
    • +
    + + + 40 +
    + + + +
    + +

    Lack of an FAQ and specialized guides

    +
      +
    • We need an FAQ for transparency that quickly informs one about what they need to know
    • +
    • There is a guide for PostgreSQL migration but that doesn't cover missing features and unknowns
    • +
    • I had to ask a whole lot of questions, and get clarifications that roped in engineering leaders within the organization
    • +
    • I've helped Googlers with Cloud Spanner, and built a previously almost impossible set of integrations, but objectively if I could struggle, that means the average builder is having it worse
    • +
    + + + 41 +
    + + + +
    + +

    Low administrative limits

    +
      +
    • When building the various integrations, had to run multiple tests, hundreds every single day in parallel, 5 QPS is super duper low and wasted lots of time and money
    • +
    • It took almost a week to get a response from the Cloud Spanner team to increase our limits for creating and tearing down databases
    • +
    • Most customers won't be privileged to have direct relationships with Cloud Spanner engineering for help
    • +
    + + + 42 +
    + + + +
    + +

    Mutation limit per commit of 20,000

    +
      +
    • The number of mutations per commit being capped at 20,000 unfortunately doesn't mention the number of properties per mutation
    • +
    • This means a bunch of insertions and updates will fail and give odd errors, unless customers manually do the calculations
    • +
    • Such constraints make it very hard for companies without highly technical engineers to operate and fix problems
    • +
    • This is a leaky abstraction beccause it exposes implementation details to users of APIs that are supposed to shield against complexity
    • +
    • Solution: this work can be offloaded to every API client, just like in the Go BigTable API client
    • +
    + + + 43 +
    + + + +
    + +

    Statistical functions weren't supported for a long time

    +
      +
    • Variance and Standard Deviation were not supported until June 2020 (way long after I was supposed to have completed developed)
    • +
    • These were necessary for Django and Ruby-on-Rails users
    • +
    • Lack of non-trivial statistical functions means composite queries can't be done with Cloud Spanner
    • +
    + + + 44 +
    + + + +
    + +

    Focusing on complexity of concepts as opposed to simplifying them

    +
      +
    • Planet scalability, and the highest availability are amazing, but what does that mean for my aunt's pizza shop, what about for a bank, what about for Twitter?
    • +
    • There are 2 kinds of READS with Cloud Spanner: Strong reads, Stale reads
    • +
    • Zero advisory on when to use each, if you ask some Cloud Spanner team members when to use them in real life, but they can all explain what these are
    • +
    • Everyone can explain why you need transactions, but somehow allow the fact that we can't run INFORMATION_SCHEMA queries in a READ-WRITE transaction
    • +
    • Everyone understands why we need non-hotspotting PRIMARY KEYs, but why this couldn't be abstracted by the database
    • +
    • Customers shouldn't even have to know about hotspotting: that should be specialized knowledge for performance engineering and Cloud Spanner should make customers so successful that this is handled by the backend
    • +
    + + + 45 +
    + + + +
    + +

    Dissonance between Client library maintainers and Cloud Spanner Engineering

    +
      +
    • Getting answers for many problems encountered by asking the folks in charge of client libraries was very slow
    • +
    • They are very overwhelmed, would have to relay questions to engineers, and that takes forever
    • +
    • Huge burden expecting customers to intricately write their own engineering patches over the Cloud Spanner libraries to support lacking features
    • +
    • Engineering mandate seemed to give direction that customers shouldn't keep transactions open for long, yet this is a case that Python experts within Google could build and remove the burden from customers
    • +
    • Guides show how to get started, until you go in and have to swim in the deep all alone: I had to experiment and dig through Cloud Spanner technical docs myself, burnt through my time and money budgets
    • +
    + + + 46 +
    + + + +
    + +

    Migration tools are manual

    +
      +
    • We've got HarbourBridge which is nice for a mid-size but non-production migration from PostgreSQL to Cloud Spanner
    • +
    • Problem is that doing a database migration can take an indefinitely long time given that some apps can't be taken offline, nor shutdown
    • +
    • No migration tools for MySQL nor for OracleDB, nor AuroraDB :-(
    • +
    • No simulation tools to convince companies to switch over to Google tools and databases entirely, by sending over traffic to Cloud Spanner and executing queries then returning results and timing, directly comparing against their current systems
    • +
    • Solving this kind of issue will rely on tools that intercept and sniff traffic, and have AST rewriters of sort -- credit to Louis Ryan with whom I discussed this idea on December 23rd 2019 at lunch in MP1
    • +
    • Less invasive tools
    • +
    + + + 47 +
    + + + +
    + +

    Migration tool: SQL sniffer -> AST rewrite -> Cloud Spanner

    +
    + + 48 +
    + + + +
    + +

    Suggestions

    +
      +
    • An aggressive approach towards building off the shelf applications, and using Cloud Spanner as customers would -- skin in the game
    • +
    • We used this approach to test out that things worked alright for django-spanner and activerecord-spanner, and it revealed lots of oddities
    • +
    • Offload functionality to the database server itself
    • +
    • API clients should implement logic to handle replay, batching of transactions within limits, counting and splitting up mutations
    • +
    • Fix low administrative limits -- it took a week
    • +
    • Make it a sin to tell customers to perform complex work on their own
    • +
    • FAQ with a bunch of listed caveats that developers can quickly ramp up to
    • +
    • Skin in the game with teams that focus on building applications with customers and not just listing features that are lacking and letting customers suffer alone
    • +
    + + + 49 +
    + + + +
    + +

    Suggestions

    +
      +
    • Look at SQLCommenter and Cloud SQL insights -- the ability to auto analyze performance for Cloud Spanner is a huge game changer that solves observability problems
    • +
    • Thinking outside the box to ensure that the teams in charge of the API clients have enough attachment to engineering and can quickly answer questions
    • +
    • Just like everyone somehow is on-call, customer success and API usability should be a tenet too
    • +
    • Follow the mission/mantra of Google aggressively, apply that for databases and work relentlessly
    • +
    + + + 50 +
    + + + +
    + +

    What do you think?

    +
    + + 51 +
    + + + +
    + +

    Shout outs to folks encountered on the journey

    +
      +
    • Many folks on the Cloud Spanner team have been very helpful
    • +
    • Pritam Shah, Vikram Manghani, John Corwin, Skylar Pottinger, Shanika Kuruppu, Ben Vandiver, Fuad Malikov, Youssef Barakat, Jiren Patel, Andrew Byrne, Damian Reeves, Xinhua Ji, Vikas Kedia, Di Xiao, Sailesh Krishnamurthy, Bala Chandrasekaran, Chris Kleinknecht, Mark Lu, Tim Graham, Nevin Heintze, Cliff Frey, Campbell Fraser and many more folks involved behind the scenes, plus the entire Cloud Spanner team
    • +
    + + + 52 +
    + + + + + + + + + +
    + + + + + + + + + + + \ No newline at end of file diff --git a/2021/04/15/google/CloudSpannerSafari_files/css b/2021/04/15/google/CloudSpannerSafari_files/css new file mode 100644 index 0000000..3d1188a --- /dev/null +++ b/2021/04/15/google/CloudSpannerSafari_files/css @@ -0,0 +1,232 @@ +/* latin */ +@font-face { + font-family: 'Droid Sans Mono'; + font-style: normal; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/droidsansmono/v14/6NUO8FuJNQ2MbkrZ5-J8lKFrp7pRef2rUGIW9g.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem6YaGs126MiZpBA-UFUK0Udc1GAK6bt6o.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem6YaGs126MiZpBA-UFUK0ddc1GAK6bt6o.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem6YaGs126MiZpBA-UFUK0Vdc1GAK6bt6o.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem6YaGs126MiZpBA-UFUK0adc1GAK6bt6o.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem6YaGs126MiZpBA-UFUK0Wdc1GAK6bt6o.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem6YaGs126MiZpBA-UFUK0Xdc1GAK6bt6o.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem6YaGs126MiZpBA-UFUK0Zdc1GAK6b.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/memnYaGs126MiZpBA-UFUKXGUdhmIqOxjaPXZSk.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/memnYaGs126MiZpBA-UFUKXGUdhvIqOxjaPXZSk.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/memnYaGs126MiZpBA-UFUKXGUdhnIqOxjaPXZSk.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/memnYaGs126MiZpBA-UFUKXGUdhoIqOxjaPXZSk.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/memnYaGs126MiZpBA-UFUKXGUdhkIqOxjaPXZSk.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/memnYaGs126MiZpBA-UFUKXGUdhlIqOxjaPXZSk.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/memnYaGs126MiZpBA-UFUKXGUdhrIqOxjaPX.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem8YaGs126MiZpBA-UFWJ0bf8pkAp6a.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem8YaGs126MiZpBA-UFUZ0bf8pkAp6a.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem8YaGs126MiZpBA-UFWZ0bf8pkAp6a.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem8YaGs126MiZpBA-UFVp0bf8pkAp6a.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem8YaGs126MiZpBA-UFWp0bf8pkAp6a.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem8YaGs126MiZpBA-UFW50bf8pkAp6a.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem8YaGs126MiZpBA-UFVZ0bf8pkAg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem5YaGs126MiZpBA-UNirkOX-hpKKSTj5PW.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem5YaGs126MiZpBA-UNirkOVuhpKKSTj5PW.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem5YaGs126MiZpBA-UNirkOXuhpKKSTj5PW.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem5YaGs126MiZpBA-UNirkOUehpKKSTj5PW.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem5YaGs126MiZpBA-UNirkOXehpKKSTj5PW.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem5YaGs126MiZpBA-UNirkOXOhpKKSTj5PW.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: url(https://fonts.gstatic.com/s/opensans/v18/mem5YaGs126MiZpBA-UNirkOUuhpKKSTjw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/2021/04/15/google/CloudSpannerSafari_files/db-ranking-rdbms.png b/2021/04/15/google/CloudSpannerSafari_files/db-ranking-rdbms.png new file mode 100644 index 0000000..a546c37 Binary files /dev/null and b/2021/04/15/google/CloudSpannerSafari_files/db-ranking-rdbms.png differ diff --git a/2021/04/15/google/CloudSpannerSafari_files/full-table-scan.png b/2021/04/15/google/CloudSpannerSafari_files/full-table-scan.png new file mode 100644 index 0000000..0c06af1 Binary files /dev/null and b/2021/04/15/google/CloudSpannerSafari_files/full-table-scan.png differ diff --git a/2021/04/15/google/CloudSpannerSafari_files/gestalt-switch.jpg b/2021/04/15/google/CloudSpannerSafari_files/gestalt-switch.jpg new file mode 100644 index 0000000..9f9780a Binary files /dev/null and b/2021/04/15/google/CloudSpannerSafari_files/gestalt-switch.jpg differ diff --git a/2021/04/15/google/CloudSpannerSafari_files/get-on-journey.png b/2021/04/15/google/CloudSpannerSafari_files/get-on-journey.png new file mode 100644 index 0000000..7586163 Binary files /dev/null and b/2021/04/15/google/CloudSpannerSafari_files/get-on-journey.png differ diff --git a/2021/04/15/google/CloudSpannerSafari_files/play.js b/2021/04/15/google/CloudSpannerSafari_files/play.js new file mode 100644 index 0000000..d62d2bf --- /dev/null +++ b/2021/04/15/google/CloudSpannerSafari_files/play.js @@ -0,0 +1,715 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
    a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
    t
    ",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
    ",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
    ",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

    ",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
    ","
    "]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
    ").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);/*! jQuery UI - v1.10.2 - 2013-03-20 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.resizable.js +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
    ",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("
    ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
    "),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css("left")),n=t(this.helper.css("top")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===n&&(e.left=t.left+(s.width-e.width),e.top=null),"nw"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidthe.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
    "),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=e(this).data("ui-resizable"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e(["Top","Right","Left","Bottom"]).each(function(e,n){s[e]=t(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,"left")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery);// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +In the absence of any formal way to specify interfaces in JavaScript, +here's a skeleton implementation of a playground transport. + + function Transport() { + // Set up any transport state (eg, make a websocket connection). + return { + Run: function(body, output, options) { + // Compile and run the program 'body' with 'options'. + // Call the 'output' callback to display program output. + return { + Kill: function() { + // Kill the running program. + } + }; + } + }; + } + + // The output callback is called multiple times, and each time it is + // passed an object of this form. + var write = { + Kind: 'string', // 'start', 'stdout', 'stderr', 'end' + Body: 'string' // content of write or end status message + } + + // The first call must be of Kind 'start' with no body. + // Subsequent calls may be of Kind 'stdout' or 'stderr' + // and must have a non-null Body string. + // The final call should be of Kind 'end' with an optional + // Body string, signifying a failure ("killed", for example). + + // The output callback must be of this form. + // See PlaygroundOutput (below) for an implementation. + function outputCallback(write) { + } +*/ + +// HTTPTransport is the default transport. +// enableVet enables running vet if a program was compiled and ran successfully. +// If vet returned any errors, display them before the output of a program. +function HTTPTransport(enableVet) { + 'use strict'; + + function playback(output, data) { + // Backwards compatibility: default values do not affect the output. + var events = data.Events || []; + var errors = data.Errors || ''; + var status = data.Status || 0; + var isTest = data.IsTest || false; + var testsFailed = data.TestsFailed || 0; + + var timeout; + output({ Kind: 'start' }); + function next() { + if (!events || events.length === 0) { + if (isTest) { + if (testsFailed > 0) { + output({ + Kind: 'system', + Body: + '\n' + + testsFailed + + ' test' + + (testsFailed > 1 ? 's' : '') + + ' failed.', + }); + } else { + output({ Kind: 'system', Body: '\nAll tests passed.' }); + } + } else { + if (status > 0) { + output({ Kind: 'end', Body: 'status ' + status + '.' }); + } else { + if (errors !== '') { + // errors are displayed only in the case of timeout. + output({ Kind: 'end', Body: errors + '.' }); + } else { + output({ Kind: 'end' }); + } + } + } + return; + } + var e = events.shift(); + if (e.Delay === 0) { + output({ Kind: e.Kind, Body: e.Message }); + next(); + return; + } + timeout = setTimeout(function() { + output({ Kind: e.Kind, Body: e.Message }); + next(); + }, e.Delay / 1000000); + } + next(); + return { + Stop: function() { + clearTimeout(timeout); + }, + }; + } + + function error(output, msg) { + output({ Kind: 'start' }); + output({ Kind: 'stderr', Body: msg }); + output({ Kind: 'end' }); + } + + function buildFailed(output, msg) { + output({ Kind: 'start' }); + output({ Kind: 'stderr', Body: msg }); + output({ Kind: 'system', Body: '\nGo build failed.' }); + } + + var seq = 0; + return { + Run: function(body, output, options) { + seq++; + var cur = seq; + var playing; + $.ajax('/compile', { + type: 'POST', + data: { version: 2, body: body, withVet: enableVet }, + dataType: 'json', + success: function(data) { + if (seq != cur) return; + if (!data) return; + if (playing != null) playing.Stop(); + if (data.Errors) { + if (data.Errors === 'process took too long') { + // Playback the output that was captured before the timeout. + playing = playback(output, data); + } else { + buildFailed(output, data.Errors); + } + return; + } + if (!data.Events) { + data.Events = []; + } + if (data.VetErrors) { + // Inject errors from the vet as the first events in the output. + data.Events.unshift({ + Message: 'Go vet exited.\n\n', + Kind: 'system', + Delay: 0, + }); + data.Events.unshift({ + Message: data.VetErrors, + Kind: 'stderr', + Delay: 0, + }); + } + + if (!enableVet || data.VetOK || data.VetErrors) { + playing = playback(output, data); + return; + } + + // In case the server support doesn't support + // compile+vet in same request signaled by the + // 'withVet' parameter above, also try the old way. + // TODO: remove this when it falls out of use. + // It is 2019-05-13 now. + $.ajax('/vet', { + data: { body: body }, + type: 'POST', + dataType: 'json', + success: function(dataVet) { + if (dataVet.Errors) { + // inject errors from the vet as the first events in the output + data.Events.unshift({ + Message: 'Go vet exited.\n\n', + Kind: 'system', + Delay: 0, + }); + data.Events.unshift({ + Message: dataVet.Errors, + Kind: 'stderr', + Delay: 0, + }); + } + playing = playback(output, data); + }, + error: function() { + playing = playback(output, data); + }, + }); + }, + error: function() { + error(output, 'Error communicating with remote server.'); + }, + }); + return { + Kill: function() { + if (playing != null) playing.Stop(); + output({ Kind: 'end', Body: 'killed' }); + }, + }; + }, + }; +} + +function SocketTransport() { + 'use strict'; + + var id = 0; + var outputs = {}; + var started = {}; + var websocket; + if (window.location.protocol == 'http:') { + websocket = new WebSocket('ws://' + window.location.host + '/socket'); + } else if (window.location.protocol == 'https:') { + websocket = new WebSocket('wss://' + window.location.host + '/socket'); + } + + websocket.onclose = function() { + console.log('websocket connection closed'); + }; + + websocket.onmessage = function(e) { + var m = JSON.parse(e.data); + var output = outputs[m.Id]; + if (output === null) return; + if (!started[m.Id]) { + output({ Kind: 'start' }); + started[m.Id] = true; + } + output({ Kind: m.Kind, Body: m.Body }); + }; + + function send(m) { + websocket.send(JSON.stringify(m)); + } + + return { + Run: function(body, output, options) { + var thisID = id + ''; + id++; + outputs[thisID] = output; + send({ Id: thisID, Kind: 'run', Body: body, Options: options }); + return { + Kill: function() { + send({ Id: thisID, Kind: 'kill' }); + }, + }; + }, + }; +} + +function PlaygroundOutput(el) { + 'use strict'; + + return function(write) { + if (write.Kind == 'start') { + el.innerHTML = ''; + return; + } + + var cl = 'system'; + if (write.Kind == 'stdout' || write.Kind == 'stderr') cl = write.Kind; + + var m = write.Body; + if (write.Kind == 'end') { + m = '\nProgram exited' + (m ? ': ' + m : '.'); + } + + if (m.indexOf('IMAGE:') === 0) { + // TODO(adg): buffer all writes before creating image + var url = 'data:image/png;base64,' + m.substr(6); + var img = document.createElement('img'); + img.src = url; + el.appendChild(img); + return; + } + + // ^L clears the screen. + var s = m.split('\x0c'); + if (s.length > 1) { + el.innerHTML = ''; + m = s.pop(); + } + + m = m.replace(/&/g, '&'); + m = m.replace(//g, '>'); + + var needScroll = el.scrollTop + el.offsetHeight == el.scrollHeight; + + var span = document.createElement('span'); + span.className = cl; + span.innerHTML = m; + el.appendChild(span); + + if (needScroll) el.scrollTop = el.scrollHeight - el.offsetHeight; + }; +} + +(function() { + function lineHighlight(error) { + var regex = /prog.go:([0-9]+)/g; + var r = regex.exec(error); + while (r) { + $('.lines div') + .eq(r[1] - 1) + .addClass('lineerror'); + r = regex.exec(error); + } + } + function highlightOutput(wrappedOutput) { + return function(write) { + if (write.Body) lineHighlight(write.Body); + wrappedOutput(write); + }; + } + function lineClear() { + $('.lineerror').removeClass('lineerror'); + } + + // opts is an object with these keys + // codeEl - code editor element + // outputEl - program output element + // runEl - run button element + // fmtEl - fmt button element (optional) + // fmtImportEl - fmt "imports" checkbox element (optional) + // shareEl - share button element (optional) + // shareURLEl - share URL text input element (optional) + // shareRedirect - base URL to redirect to on share (optional) + // toysEl - toys select element (optional) + // enableHistory - enable using HTML5 history API (optional) + // transport - playground transport to use (default is HTTPTransport) + // enableShortcuts - whether to enable shortcuts (Ctrl+S/Cmd+S to save) (default is false) + // enableVet - enable running vet and displaying its errors + function playground(opts) { + var code = $(opts.codeEl); + var transport = opts['transport'] || new HTTPTransport(opts['enableVet']); + var running; + + // autoindent helpers. + function insertTabs(n) { + // find the selection start and end + var start = code[0].selectionStart; + var end = code[0].selectionEnd; + // split the textarea content into two, and insert n tabs + var v = code[0].value; + var u = v.substr(0, start); + for (var i = 0; i < n; i++) { + u += '\t'; + } + u += v.substr(end); + // set revised content + code[0].value = u; + // reset caret position after inserted tabs + code[0].selectionStart = start + n; + code[0].selectionEnd = start + n; + } + function autoindent(el) { + var curpos = el.selectionStart; + var tabs = 0; + while (curpos > 0) { + curpos--; + if (el.value[curpos] == '\t') { + tabs++; + } else if (tabs > 0 || el.value[curpos] == '\n') { + break; + } + } + setTimeout(function() { + insertTabs(tabs); + }, 1); + } + + // NOTE(cbro): e is a jQuery event, not a DOM event. + function handleSaveShortcut(e) { + if (e.isDefaultPrevented()) return false; + if (!e.metaKey && !e.ctrlKey) return false; + if (e.key != 'S' && e.key != 's') return false; + + e.preventDefault(); + + // Share and save + share(function(url) { + window.location.href = url + '.go?download=true'; + }); + + return true; + } + + function keyHandler(e) { + if (opts.enableShortcuts && handleSaveShortcut(e)) return; + + if (e.keyCode == 9 && !e.ctrlKey) { + // tab (but not ctrl-tab) + insertTabs(1); + e.preventDefault(); + return false; + } + if (e.keyCode == 13) { + // enter + if (e.shiftKey) { + // +shift + run(); + e.preventDefault(); + return false; + } + if (e.ctrlKey) { + // +control + fmt(); + e.preventDefault(); + } else { + autoindent(e.target); + } + } + return true; + } + code.unbind('keydown').bind('keydown', keyHandler); + var outdiv = $(opts.outputEl).empty(); + var output = $('
    ').appendTo(outdiv);
    +
    +    function body() {
    +      return $(opts.codeEl).val();
    +    }
    +    function setBody(text) {
    +      $(opts.codeEl).val(text);
    +    }
    +    function origin(href) {
    +      return ('' + href)
    +        .split('/')
    +        .slice(0, 3)
    +        .join('/');
    +    }
    +
    +    var pushedEmpty = window.location.pathname == '/';
    +    function inputChanged() {
    +      if (pushedEmpty) {
    +        return;
    +      }
    +      pushedEmpty = true;
    +      $(opts.shareURLEl).hide();
    +      window.history.pushState(null, '', '/');
    +    }
    +    function popState(e) {
    +      if (e === null) {
    +        return;
    +      }
    +      if (e && e.state && e.state.code) {
    +        setBody(e.state.code);
    +      }
    +    }
    +    var rewriteHistory = false;
    +    if (
    +      window.history &&
    +      window.history.pushState &&
    +      window.addEventListener &&
    +      opts.enableHistory
    +    ) {
    +      rewriteHistory = true;
    +      code[0].addEventListener('input', inputChanged);
    +      window.addEventListener('popstate', popState);
    +    }
    +
    +    function setError(error) {
    +      if (running) running.Kill();
    +      lineClear();
    +      lineHighlight(error);
    +      output
    +        .empty()
    +        .addClass('error')
    +        .text(error);
    +    }
    +    function loading() {
    +      lineClear();
    +      if (running) running.Kill();
    +      output.removeClass('error').text('Waiting for remote server...');
    +    }
    +    function run() {
    +      loading();
    +      running = transport.Run(
    +        body(),
    +        highlightOutput(PlaygroundOutput(output[0]))
    +      );
    +    }
    +
    +    function fmt() {
    +      loading();
    +      var data = { body: body() };
    +      if ($(opts.fmtImportEl).is(':checked')) {
    +        data['imports'] = 'true';
    +      }
    +      $.ajax('/fmt', {
    +        data: data,
    +        type: 'POST',
    +        dataType: 'json',
    +        success: function(data) {
    +          if (data.Error) {
    +            setError(data.Error);
    +          } else {
    +            setBody(data.Body);
    +            setError('');
    +          }
    +        },
    +      });
    +    }
    +
    +    var shareURL; // jQuery element to show the shared URL.
    +    var sharing = false; // true if there is a pending request.
    +    var shareCallbacks = [];
    +    function share(opt_callback) {
    +      if (opt_callback) shareCallbacks.push(opt_callback);
    +
    +      if (sharing) return;
    +      sharing = true;
    +
    +      var sharingData = body();
    +      $.ajax('/share', {
    +        processData: false,
    +        data: sharingData,
    +        type: 'POST',
    +        contentType: 'text/plain; charset=utf-8',
    +        complete: function(xhr) {
    +          sharing = false;
    +          if (xhr.status != 200) {
    +            alert('Server error; try again.');
    +            return;
    +          }
    +          if (opts.shareRedirect) {
    +            window.location = opts.shareRedirect + xhr.responseText;
    +          }
    +          var path = '/p/' + xhr.responseText;
    +          var url = origin(window.location) + path;
    +
    +          for (var i = 0; i < shareCallbacks.length; i++) {
    +            shareCallbacks[i](url);
    +          }
    +          shareCallbacks = [];
    +
    +          if (shareURL) {
    +            shareURL
    +              .show()
    +              .val(url)
    +              .focus()
    +              .select();
    +
    +            if (rewriteHistory) {
    +              var historyData = { code: sharingData };
    +              window.history.pushState(historyData, '', path);
    +              pushedEmpty = false;
    +            }
    +          }
    +        },
    +      });
    +    }
    +
    +    $(opts.runEl).click(run);
    +    $(opts.fmtEl).click(fmt);
    +
    +    if (
    +      opts.shareEl !== null &&
    +      (opts.shareURLEl !== null || opts.shareRedirect !== null)
    +    ) {
    +      if (opts.shareURLEl) {
    +        shareURL = $(opts.shareURLEl).hide();
    +      }
    +      $(opts.shareEl).click(function() {
    +        share();
    +      });
    +    }
    +
    +    if (opts.toysEl !== null) {
    +      $(opts.toysEl).bind('change', function() {
    +        var toy = $(this).val();
    +        $.ajax('/doc/play/' + toy, {
    +          processData: false,
    +          type: 'GET',
    +          complete: function(xhr) {
    +            if (xhr.status != 200) {
    +              alert('Server error; try again.');
    +              return;
    +            }
    +            setBody(xhr.responseText);
    +          },
    +        });
    +      });
    +    }
    +  }
    +
    +  window.playground = playground;
    +})();
    +// Copyright 2012 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +function initPlayground(transport) {
    +  'use strict';
    +
    +  function text(node) {
    +    var s = '';
    +    for (var i = 0; i < node.childNodes.length; i++) {
    +      var n = node.childNodes[i];
    +      if (n.nodeType === 1) {
    +        if (n.tagName === 'BUTTON') continue;
    +        if (n.tagName === 'SPAN' && n.className === 'number') continue;
    +        if (n.tagName === 'DIV' || n.tagName === 'BR' || n.tagName === 'PRE') {
    +          s += '\n';
    +        }
    +        s += text(n);
    +        continue;
    +      }
    +      if (n.nodeType === 3) {
    +        s += n.nodeValue;
    +      }
    +    }
    +    return s.replace('\xA0', ' '); // replace non-breaking spaces
    +  }
    +
    +  // When presenter notes are enabled, the index passed
    +  // here will identify the playground to be synced
    +  function init(code, index) {
    +    var output = document.createElement('div');
    +    var outpre = document.createElement('pre');
    +    var running;
    +
    +    if ($ && $(output).resizable) {
    +      $(output).resizable({
    +        handles: 'n,w,nw',
    +        minHeight: 27,
    +        minWidth: 135,
    +        maxHeight: 608,
    +        maxWidth: 990,
    +      });
    +    }
    +
    +    function onKill() {
    +      if (running) running.Kill();
    +      if (window.notesEnabled) updatePlayStorage('onKill', index);
    +    }
    +
    +    function onRun(e) {
    +      var sk = e.shiftKey || localStorage.getItem('play-shiftKey') === 'true';
    +      if (running) running.Kill();
    +      output.style.display = 'block';
    +      outpre.textContent = '';
    +      run1.style.display = 'none';
    +      var options = { Race: sk };
    +      running = transport.Run(text(code), PlaygroundOutput(outpre), options);
    +      if (window.notesEnabled) updatePlayStorage('onRun', index, e);
    +    }
    +
    +    function onClose() {
    +      if (running) running.Kill();
    +      output.style.display = 'none';
    +      run1.style.display = 'inline-block';
    +      if (window.notesEnabled) updatePlayStorage('onClose', index);
    +    }
    +
    +    if (window.notesEnabled) {
    +      playgroundHandlers.onRun.push(onRun);
    +      playgroundHandlers.onClose.push(onClose);
    +      playgroundHandlers.onKill.push(onKill);
    +    }
    +
    +    var run1 = document.createElement('button');
    +    run1.textContent = 'Run';
    +    run1.className = 'run';
    +    run1.addEventListener('click', onRun, false);
    +    var run2 = document.createElement('button');
    +    run2.className = 'run';
    +    run2.textContent = 'Run';
    +    run2.addEventListener('click', onRun, false);
    +    var kill = document.createElement('button');
    +    kill.className = 'kill';
    +    kill.textContent = 'Kill';
    +    kill.addEventListener('click', onKill, false);
    +    var close = document.createElement('button');
    +    close.className = 'close';
    +    close.textContent = 'Close';
    +    close.addEventListener('click', onClose, false);
    +
    +    var button = document.createElement('div');
    +    button.classList.add('buttons');
    +    button.appendChild(run1);
    +    // Hack to simulate insertAfter
    +    code.parentNode.insertBefore(button, code.nextSibling);
    +
    +    var buttons = document.createElement('div');
    +    buttons.classList.add('buttons');
    +    buttons.appendChild(run2);
    +    buttons.appendChild(kill);
    +    buttons.appendChild(close);
    +
    +    output.classList.add('output');
    +    output.appendChild(buttons);
    +    output.appendChild(outpre);
    +    output.style.display = 'none';
    +    code.parentNode.insertBefore(output, button.nextSibling);
    +  }
    +
    +  var play = document.querySelectorAll('div.playground');
    +  for (var i = 0; i < play.length; i++) {
    +    init(play[i], i);
    +  }
    +}
    +
    +initPlayground(new SocketTransport());
    diff --git a/2021/04/15/google/CloudSpannerSafari_files/query-result-expectation.png b/2021/04/15/google/CloudSpannerSafari_files/query-result-expectation.png
    new file mode 100644
    index 0000000..5410108
    Binary files /dev/null and b/2021/04/15/google/CloudSpannerSafari_files/query-result-expectation.png differ
    diff --git a/2021/04/15/google/CloudSpannerSafari_files/safari-cheetah.png b/2021/04/15/google/CloudSpannerSafari_files/safari-cheetah.png
    new file mode 100644
    index 0000000..61849d0
    Binary files /dev/null and b/2021/04/15/google/CloudSpannerSafari_files/safari-cheetah.png differ
    diff --git a/2021/04/15/google/CloudSpannerSafari_files/shrug.png b/2021/04/15/google/CloudSpannerSafari_files/shrug.png
    new file mode 100644
    index 0000000..3b1fac3
    Binary files /dev/null and b/2021/04/15/google/CloudSpannerSafari_files/shrug.png differ
    diff --git a/2021/04/15/google/CloudSpannerSafari_files/slides.js b/2021/04/15/google/CloudSpannerSafari_files/slides.js
    new file mode 100644
    index 0000000..7c1229e
    --- /dev/null
    +++ b/2021/04/15/google/CloudSpannerSafari_files/slides.js
    @@ -0,0 +1,635 @@
    +// Copyright 2012 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +var PERMANENT_URL_PREFIX = '/static/';
    +
    +var SLIDE_CLASSES = ['far-past', 'past', 'current', 'next', 'far-next'];
    +
    +var PM_TOUCH_SENSITIVITY = 15;
    +
    +var curSlide;
    +
    +/* ---------------------------------------------------------------------- */
    +/* classList polyfill by Eli Grey
    + * (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */
    +
    +if (
    +  typeof document !== 'undefined' &&
    +  !('classList' in document.createElement('a'))
    +) {
    +  (function(view) {
    +    var classListProp = 'classList',
    +      protoProp = 'prototype',
    +      elemCtrProto = (view.HTMLElement || view.Element)[protoProp],
    +      objCtr = Object;
    +    (strTrim =
    +      String[protoProp].trim ||
    +      function() {
    +        return this.replace(/^\s+|\s+$/g, '');
    +      }),
    +      (arrIndexOf =
    +        Array[protoProp].indexOf ||
    +        function(item) {
    +          for (var i = 0, len = this.length; i < len; i++) {
    +            if (i in this && this[i] === item) {
    +              return i;
    +            }
    +          }
    +          return -1;
    +        }),
    +      // Vendors: please allow content code to instantiate DOMExceptions
    +      (DOMEx = function(type, message) {
    +        this.name = type;
    +        this.code = DOMException[type];
    +        this.message = message;
    +      }),
    +      (checkTokenAndGetIndex = function(classList, token) {
    +        if (token === '') {
    +          throw new DOMEx(
    +            'SYNTAX_ERR',
    +            'An invalid or illegal string was specified'
    +          );
    +        }
    +        if (/\s/.test(token)) {
    +          throw new DOMEx(
    +            'INVALID_CHARACTER_ERR',
    +            'String contains an invalid character'
    +          );
    +        }
    +        return arrIndexOf.call(classList, token);
    +      }),
    +      (ClassList = function(elem) {
    +        var trimmedClasses = strTrim.call(elem.className),
    +          classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [];
    +        for (var i = 0, len = classes.length; i < len; i++) {
    +          this.push(classes[i]);
    +        }
    +        this._updateClassName = function() {
    +          elem.className = this.toString();
    +        };
    +      }),
    +      (classListProto = ClassList[protoProp] = []),
    +      (classListGetter = function() {
    +        return new ClassList(this);
    +      });
    +    // Most DOMException implementations don't allow calling DOMException's toString()
    +    // on non-DOMExceptions. Error's toString() is sufficient here.
    +    DOMEx[protoProp] = Error[protoProp];
    +    classListProto.item = function(i) {
    +      return this[i] || null;
    +    };
    +    classListProto.contains = function(token) {
    +      token += '';
    +      return checkTokenAndGetIndex(this, token) !== -1;
    +    };
    +    classListProto.add = function(token) {
    +      token += '';
    +      if (checkTokenAndGetIndex(this, token) === -1) {
    +        this.push(token);
    +        this._updateClassName();
    +      }
    +    };
    +    classListProto.remove = function(token) {
    +      token += '';
    +      var index = checkTokenAndGetIndex(this, token);
    +      if (index !== -1) {
    +        this.splice(index, 1);
    +        this._updateClassName();
    +      }
    +    };
    +    classListProto.toggle = function(token) {
    +      token += '';
    +      if (checkTokenAndGetIndex(this, token) === -1) {
    +        this.add(token);
    +      } else {
    +        this.remove(token);
    +      }
    +    };
    +    classListProto.toString = function() {
    +      return this.join(' ');
    +    };
    +
    +    if (objCtr.defineProperty) {
    +      var classListPropDesc = {
    +        get: classListGetter,
    +        enumerable: true,
    +        configurable: true,
    +      };
    +      try {
    +        objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
    +      } catch (ex) {
    +        // IE 8 doesn't support enumerable:true
    +        if (ex.number === -0x7ff5ec54) {
    +          classListPropDesc.enumerable = false;
    +          objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
    +        }
    +      }
    +    } else if (objCtr[protoProp].__defineGetter__) {
    +      elemCtrProto.__defineGetter__(classListProp, classListGetter);
    +    }
    +  })(self);
    +}
    +/* ---------------------------------------------------------------------- */
    +
    +/* Slide movement */
    +
    +function hideHelpText() {
    +  document.getElementById('help').style.display = 'none';
    +}
    +
    +function getSlideEl(no) {
    +  if (no < 0 || no >= slideEls.length) {
    +    return null;
    +  } else {
    +    return slideEls[no];
    +  }
    +}
    +
    +function updateSlideClass(slideNo, className) {
    +  var el = getSlideEl(slideNo);
    +
    +  if (!el) {
    +    return;
    +  }
    +
    +  if (className) {
    +    el.classList.add(className);
    +  }
    +
    +  for (var i in SLIDE_CLASSES) {
    +    if (className != SLIDE_CLASSES[i]) {
    +      el.classList.remove(SLIDE_CLASSES[i]);
    +    }
    +  }
    +}
    +
    +function updateSlides() {
    +  if (window.trackPageview) window.trackPageview();
    +
    +  for (var i = 0; i < slideEls.length; i++) {
    +    switch (i) {
    +      case curSlide - 2:
    +        updateSlideClass(i, 'far-past');
    +        break;
    +      case curSlide - 1:
    +        updateSlideClass(i, 'past');
    +        break;
    +      case curSlide:
    +        updateSlideClass(i, 'current');
    +        break;
    +      case curSlide + 1:
    +        updateSlideClass(i, 'next');
    +        break;
    +      case curSlide + 2:
    +        updateSlideClass(i, 'far-next');
    +        break;
    +      default:
    +        updateSlideClass(i);
    +        break;
    +    }
    +  }
    +
    +  triggerLeaveEvent(curSlide - 1);
    +  triggerEnterEvent(curSlide);
    +
    +  window.setTimeout(function() {
    +    // Hide after the slide
    +    disableSlideFrames(curSlide - 2);
    +  }, 301);
    +
    +  enableSlideFrames(curSlide - 1);
    +  enableSlideFrames(curSlide + 2);
    +
    +  updateHash();
    +}
    +
    +function prevSlide() {
    +  hideHelpText();
    +  if (curSlide > 0) {
    +    curSlide--;
    +
    +    updateSlides();
    +  }
    +
    +  if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide);
    +}
    +
    +function nextSlide() {
    +  hideHelpText();
    +  if (curSlide < slideEls.length - 1) {
    +    curSlide++;
    +
    +    updateSlides();
    +  }
    +
    +  if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide);
    +}
    +
    +/* Slide events */
    +
    +function triggerEnterEvent(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var onEnter = el.getAttribute('onslideenter');
    +  if (onEnter) {
    +    new Function(onEnter).call(el);
    +  }
    +
    +  var evt = document.createEvent('Event');
    +  evt.initEvent('slideenter', true, true);
    +  evt.slideNumber = no + 1; // Make it readable
    +
    +  el.dispatchEvent(evt);
    +}
    +
    +function triggerLeaveEvent(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var onLeave = el.getAttribute('onslideleave');
    +  if (onLeave) {
    +    new Function(onLeave).call(el);
    +  }
    +
    +  var evt = document.createEvent('Event');
    +  evt.initEvent('slideleave', true, true);
    +  evt.slideNumber = no + 1; // Make it readable
    +
    +  el.dispatchEvent(evt);
    +}
    +
    +/* Touch events */
    +
    +function handleTouchStart(event) {
    +  if (event.touches.length == 1) {
    +    touchDX = 0;
    +    touchDY = 0;
    +
    +    touchStartX = event.touches[0].pageX;
    +    touchStartY = event.touches[0].pageY;
    +
    +    document.body.addEventListener('touchmove', handleTouchMove, true);
    +    document.body.addEventListener('touchend', handleTouchEnd, true);
    +  }
    +}
    +
    +function handleTouchMove(event) {
    +  if (event.touches.length > 1) {
    +    cancelTouch();
    +  } else {
    +    touchDX = event.touches[0].pageX - touchStartX;
    +    touchDY = event.touches[0].pageY - touchStartY;
    +    event.preventDefault();
    +  }
    +}
    +
    +function handleTouchEnd(event) {
    +  var dx = Math.abs(touchDX);
    +  var dy = Math.abs(touchDY);
    +
    +  if (dx > PM_TOUCH_SENSITIVITY && dy < (dx * 2) / 3) {
    +    if (touchDX > 0) {
    +      prevSlide();
    +    } else {
    +      nextSlide();
    +    }
    +  }
    +
    +  cancelTouch();
    +}
    +
    +function cancelTouch() {
    +  document.body.removeEventListener('touchmove', handleTouchMove, true);
    +  document.body.removeEventListener('touchend', handleTouchEnd, true);
    +}
    +
    +/* Preloading frames */
    +
    +function disableSlideFrames(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var frames = el.getElementsByTagName('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    disableFrame(frame);
    +  }
    +}
    +
    +function enableSlideFrames(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var frames = el.getElementsByTagName('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    enableFrame(frame);
    +  }
    +}
    +
    +function disableFrame(frame) {
    +  frame.src = 'about:blank';
    +}
    +
    +function enableFrame(frame) {
    +  var src = frame._src;
    +
    +  if (frame.src != src && src != 'about:blank') {
    +    frame.src = src;
    +  }
    +}
    +
    +function setupFrames() {
    +  var frames = document.querySelectorAll('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    frame._src = frame.src;
    +    disableFrame(frame);
    +  }
    +
    +  enableSlideFrames(curSlide);
    +  enableSlideFrames(curSlide + 1);
    +  enableSlideFrames(curSlide + 2);
    +}
    +
    +function setupInteraction() {
    +  /* Clicking and tapping */
    +
    +  var el = document.createElement('div');
    +  el.className = 'slide-area';
    +  el.id = 'prev-slide-area';
    +  el.addEventListener('click', prevSlide, false);
    +  document.querySelector('section.slides').appendChild(el);
    +
    +  var el = document.createElement('div');
    +  el.className = 'slide-area';
    +  el.id = 'next-slide-area';
    +  el.addEventListener('click', nextSlide, false);
    +  document.querySelector('section.slides').appendChild(el);
    +
    +  /* Swiping */
    +
    +  document.body.addEventListener('touchstart', handleTouchStart, false);
    +}
    +
    +/* Hash functions */
    +
    +function getCurSlideFromHash() {
    +  var slideNo = parseInt(location.hash.substr(1));
    +
    +  if (slideNo) {
    +    curSlide = slideNo - 1;
    +  } else {
    +    curSlide = 0;
    +  }
    +}
    +
    +function updateHash() {
    +  location.replace('#' + (curSlide + 1));
    +}
    +
    +/* Event listeners */
    +
    +function handleBodyKeyDown(event) {
    +  // If we're in a code element, only handle pgup/down.
    +  var inCode = event.target.classList.contains('code');
    +
    +  switch (event.keyCode) {
    +    case 78: // 'N' opens presenter notes window
    +      if (!inCode && notesEnabled) toggleNotesWindow();
    +      break;
    +    case 72: // 'H' hides the help text
    +    case 27: // escape key
    +      if (!inCode) hideHelpText();
    +      break;
    +
    +    case 39: // right arrow
    +    case 13: // Enter
    +    case 32: // space
    +      if (inCode) break;
    +    case 34: // PgDn
    +      nextSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 37: // left arrow
    +    case 8: // Backspace
    +      if (inCode) break;
    +    case 33: // PgUp
    +      prevSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 40: // down arrow
    +      if (inCode) break;
    +      nextSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 38: // up arrow
    +      if (inCode) break;
    +      prevSlide();
    +      event.preventDefault();
    +      break;
    +  }
    +}
    +
    +function scaleSmallViewports() {
    +  var el = document.querySelector('section.slides');
    +  var transform = '';
    +  var sWidthPx = 1250;
    +  var sHeightPx = 750;
    +  var sAspectRatio = sWidthPx / sHeightPx;
    +  var wAspectRatio = window.innerWidth / window.innerHeight;
    +
    +  if (wAspectRatio <= sAspectRatio && window.innerWidth < sWidthPx) {
    +    transform = 'scale(' + window.innerWidth / sWidthPx + ')';
    +  } else if (window.innerHeight < sHeightPx) {
    +    transform = 'scale(' + window.innerHeight / sHeightPx + ')';
    +  }
    +  el.style.transform = transform;
    +}
    +
    +function addEventListeners() {
    +  document.addEventListener('keydown', handleBodyKeyDown, false);
    +  var resizeTimeout;
    +  window.addEventListener('resize', function() {
    +    // throttle resize events
    +    window.clearTimeout(resizeTimeout);
    +    resizeTimeout = window.setTimeout(function() {
    +      resizeTimeout = null;
    +      scaleSmallViewports();
    +    }, 50);
    +  });
    +
    +  // Force reset transform property of section.slides when printing page.
    +  // Use both onbeforeprint and matchMedia for compatibility with different browsers.
    +  var beforePrint = function() {
    +    var el = document.querySelector('section.slides');
    +    el.style.transform = '';
    +  };
    +  window.onbeforeprint = beforePrint;
    +  if (window.matchMedia) {
    +    var mediaQueryList = window.matchMedia('print');
    +    mediaQueryList.addListener(function(mql) {
    +      if (mql.matches) beforePrint();
    +    });
    +  }
    +}
    +
    +/* Initialization */
    +
    +function addFontStyle() {
    +  var el = document.createElement('link');
    +  el.rel = 'stylesheet';
    +  el.type = 'text/css';
    +  el.href =
    +    '//fonts.googleapis.com/css?family=' +
    +    'Open+Sans:regular,semibold,italic,italicsemibold|Droid+Sans+Mono';
    +
    +  document.body.appendChild(el);
    +}
    +
    +function addGeneralStyle() {
    +  var el = document.createElement('link');
    +  el.rel = 'stylesheet';
    +  el.type = 'text/css';
    +  el.href = PERMANENT_URL_PREFIX + 'styles.css';
    +  document.body.appendChild(el);
    +
    +  var el = document.createElement('meta');
    +  el.name = 'viewport';
    +  el.content = 'width=device-width,height=device-height,initial-scale=1';
    +  document.querySelector('head').appendChild(el);
    +
    +  var el = document.createElement('meta');
    +  el.name = 'apple-mobile-web-app-capable';
    +  el.content = 'yes';
    +  document.querySelector('head').appendChild(el);
    +
    +  scaleSmallViewports();
    +}
    +
    +function handleDomLoaded() {
    +  slideEls = document.querySelectorAll('section.slides > article');
    +
    +  setupFrames();
    +
    +  addFontStyle();
    +  addGeneralStyle();
    +  addEventListeners();
    +
    +  updateSlides();
    +
    +  setupInteraction();
    +
    +  if (
    +    window.location.hostname == 'localhost' ||
    +    window.location.hostname == '127.0.0.1' ||
    +    window.location.hostname == '::1'
    +  ) {
    +    hideHelpText();
    +  }
    +
    +  document.body.classList.add('loaded');
    +
    +  setupNotesSync();
    +}
    +
    +function initialize() {
    +  getCurSlideFromHash();
    +
    +  if (window['_DEBUG']) {
    +    PERMANENT_URL_PREFIX = '../';
    +  }
    +
    +  if (window['_DCL']) {
    +    handleDomLoaded();
    +  } else {
    +    document.addEventListener('DOMContentLoaded', handleDomLoaded, false);
    +  }
    +}
    +
    +// If ?debug exists then load the script relative instead of absolute
    +if (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) {
    +  document.addEventListener(
    +    'DOMContentLoaded',
    +    function() {
    +      // Avoid missing the DomContentLoaded event
    +      window['_DCL'] = true;
    +    },
    +    false
    +  );
    +
    +  window['_DEBUG'] = true;
    +  var script = document.createElement('script');
    +  script.type = 'text/javascript';
    +  script.src = '../slides.js';
    +  var s = document.getElementsByTagName('script')[0];
    +  s.parentNode.insertBefore(script, s);
    +
    +  // Remove this script
    +  s.parentNode.removeChild(s);
    +} else {
    +  initialize();
    +}
    +
    +/* Synchronize windows when notes are enabled */
    +
    +function setupNotesSync() {
    +  if (!notesEnabled) return;
    +
    +  function setupPlayResizeSync() {
    +    var out = document.getElementsByClassName('output');
    +    for (var i = 0; i < out.length; i++) {
    +      $(out[i]).bind('resize', function(event) {
    +        if ($(event.target).hasClass('ui-resizable')) {
    +          localStorage.setItem('play-index', i);
    +          localStorage.setItem('output-style', out[i].style.cssText);
    +        }
    +      });
    +    }
    +  }
    +  function setupPlayCodeSync() {
    +    var play = document.querySelectorAll('div.playground');
    +    for (var i = 0; i < play.length; i++) {
    +      play[i].addEventListener('input', inputHandler, false);
    +
    +      function inputHandler(e) {
    +        localStorage.setItem('play-index', i);
    +        localStorage.setItem('play-code', e.target.innerHTML);
    +      }
    +    }
    +  }
    +
    +  setupPlayCodeSync();
    +  setupPlayResizeSync();
    +  localStorage.setItem(destSlideKey(), curSlide);
    +  window.addEventListener('storage', updateOtherWindow, false);
    +}
    +
    +// An update to local storage is caught only by the other window
    +// The triggering window does not handle any sync actions
    +function updateOtherWindow(e) {
    +  // Ignore remove storage events which are not meant to update the other window
    +  var isRemoveStorageEvent = !e.newValue;
    +  if (isRemoveStorageEvent) return;
    +
    +  var destSlide = localStorage.getItem(destSlideKey());
    +  while (destSlide > curSlide) {
    +    nextSlide();
    +  }
    +  while (destSlide < curSlide) {
    +    prevSlide();
    +  }
    +
    +  updatePlay(e);
    +  updateNotes();
    +}
    diff --git a/2021/04/15/google/CloudSpannerSafari_files/sqlsniff-AST-rewriter.png b/2021/04/15/google/CloudSpannerSafari_files/sqlsniff-AST-rewriter.png
    new file mode 100644
    index 0000000..aaad9ff
    Binary files /dev/null and b/2021/04/15/google/CloudSpannerSafari_files/sqlsniff-AST-rewriter.png differ
    diff --git a/2021/04/15/google/CloudSpannerSafari_files/styles.css b/2021/04/15/google/CloudSpannerSafari_files/styles.css
    new file mode 100644
    index 0000000..5edfde9
    --- /dev/null
    +++ b/2021/04/15/google/CloudSpannerSafari_files/styles.css
    @@ -0,0 +1,553 @@
    +@media screen {
    +  /* Framework */
    +  html {
    +    height: 100%;
    +  }
    +
    +  body {
    +    margin: 0;
    +    padding: 0;
    +
    +    display: block !important;
    +
    +    height: 100%;
    +    height: 100vh;
    +
    +    overflow: hidden;
    +
    +    background: rgb(215, 215, 215);
    +    background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -webkit-gradient(
    +      radial,
    +      50% 50%,
    +      0,
    +      50% 50%,
    +      500,
    +      from(rgb(240, 240, 240)),
    +      to(rgb(190, 190, 190))
    +    );
    +
    +    -webkit-font-smoothing: antialiased;
    +  }
    +
    +  .slides {
    +    width: 100%;
    +    height: 100%;
    +    left: 0;
    +    top: 0;
    +
    +    position: absolute;
    +
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +
    +  .slides > article {
    +    display: block;
    +
    +    position: absolute;
    +    overflow: hidden;
    +
    +    width: 900px;
    +    height: 700px;
    +
    +    left: 50%;
    +    top: 50%;
    +
    +    margin-left: -450px;
    +    margin-top: -350px;
    +
    +    padding: 40px 60px;
    +
    +    box-sizing: border-box;
    +    -o-box-sizing: border-box;
    +    -moz-box-sizing: border-box;
    +    -webkit-box-sizing: border-box;
    +
    +    border-radius: 10px;
    +    -o-border-radius: 10px;
    +    -moz-border-radius: 10px;
    +    -webkit-border-radius: 10px;
    +
    +    background-color: white;
    +
    +    border: 1px solid rgba(0, 0, 0, 0.3);
    +
    +    transition: transform 0.3s ease-out;
    +    -o-transition: -o-transform 0.3s ease-out;
    +    -moz-transition: -moz-transform 0.3s ease-out;
    +    -webkit-transition: -webkit-transform 0.3s ease-out;
    +  }
    +  .slides.layout-widescreen > article {
    +    margin-left: -550px;
    +    width: 1100px;
    +  }
    +  .slides.layout-faux-widescreen > article {
    +    margin-left: -550px;
    +    width: 1100px;
    +
    +    padding: 40px 160px;
    +  }
    +
    +  .slides.layout-widescreen > article:not(.nobackground):not(.biglogo),
    +  .slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) {
    +    background-position-x: 0, 840px;
    +  }
    +
    +  /* Clickable/tappable areas */
    +
    +  .slide-area {
    +    z-index: 1000;
    +
    +    position: absolute;
    +    left: 0;
    +    top: 0;
    +    width: 150px;
    +    height: 700px;
    +
    +    left: 50%;
    +    top: 50%;
    +
    +    cursor: pointer;
    +    margin-top: -350px;
    +
    +    tap-highlight-color: transparent;
    +    -o-tap-highlight-color: transparent;
    +    -moz-tap-highlight-color: transparent;
    +    -webkit-tap-highlight-color: transparent;
    +  }
    +  #prev-slide-area {
    +    margin-left: -550px;
    +  }
    +  #next-slide-area {
    +    margin-left: 400px;
    +  }
    +  .slides.layout-widescreen #prev-slide-area,
    +  .slides.layout-faux-widescreen #prev-slide-area {
    +    margin-left: -650px;
    +  }
    +  .slides.layout-widescreen #next-slide-area,
    +  .slides.layout-faux-widescreen #next-slide-area {
    +    margin-left: 500px;
    +  }
    +
    +  /* Slides */
    +
    +  .slides > article {
    +    display: none;
    +  }
    +  .slides > article.far-past {
    +    display: block;
    +    transform: translate(-2040px);
    +    -o-transform: translate(-2040px);
    +    -moz-transform: translate(-2040px);
    +    -webkit-transform: translate3d(-2040px, 0, 0);
    +  }
    +  .slides > article.past {
    +    display: block;
    +    transform: translate(-1020px);
    +    -o-transform: translate(-1020px);
    +    -moz-transform: translate(-1020px);
    +    -webkit-transform: translate3d(-1020px, 0, 0);
    +  }
    +  .slides > article.current {
    +    display: block;
    +    transform: translate(0);
    +    -o-transform: translate(0);
    +    -moz-transform: translate(0);
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +  .slides > article.next {
    +    display: block;
    +    transform: translate(1020px);
    +    -o-transform: translate(1020px);
    +    -moz-transform: translate(1020px);
    +    -webkit-transform: translate3d(1020px, 0, 0);
    +  }
    +  .slides > article.far-next {
    +    display: block;
    +    transform: translate(2040px);
    +    -o-transform: translate(2040px);
    +    -moz-transform: translate(2040px);
    +    -webkit-transform: translate3d(2040px, 0, 0);
    +  }
    +
    +  .slides.layout-widescreen > article.far-past,
    +  .slides.layout-faux-widescreen > article.far-past {
    +    display: block;
    +    transform: translate(-2260px);
    +    -o-transform: translate(-2260px);
    +    -moz-transform: translate(-2260px);
    +    -webkit-transform: translate3d(-2260px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.past,
    +  .slides.layout-faux-widescreen > article.past {
    +    display: block;
    +    transform: translate(-1130px);
    +    -o-transform: translate(-1130px);
    +    -moz-transform: translate(-1130px);
    +    -webkit-transform: translate3d(-1130px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.current,
    +  .slides.layout-faux-widescreen > article.current {
    +    display: block;
    +    transform: translate(0);
    +    -o-transform: translate(0);
    +    -moz-transform: translate(0);
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.next,
    +  .slides.layout-faux-widescreen > article.next {
    +    display: block;
    +    transform: translate(1130px);
    +    -o-transform: translate(1130px);
    +    -moz-transform: translate(1130px);
    +    -webkit-transform: translate3d(1130px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.far-next,
    +  .slides.layout-faux-widescreen > article.far-next {
    +    display: block;
    +    transform: translate(2260px);
    +    -o-transform: translate(2260px);
    +    -moz-transform: translate(2260px);
    +    -webkit-transform: translate3d(2260px, 0, 0);
    +  }
    +}
    +
    +@media print {
    +  /* Set page layout */
    +  @page {
    +    size: A4 landscape;
    +  }
    +
    +  body {
    +    display: block !important;
    +  }
    +
    +  .slides > article {
    +    display: block;
    +
    +    position: relative;
    +
    +    page-break-inside: never;
    +    page-break-after: always;
    +
    +    overflow: hidden;
    +  }
    +
    +  h2 {
    +    position: static !important;
    +    margin-top: 400px !important;
    +    margin-bottom: 100px !important;
    +  }
    +
    +  div.code {
    +    background: rgb(240, 240, 240);
    +  }
    +
    +  /* Add explicit links */
    +  a:link:after,
    +  a:visited:after {
    +    content: ' (' attr(href) ') ';
    +    font-size: 50%;
    +  }
    +
    +  #help {
    +    display: none;
    +    visibility: hidden;
    +  }
    +}
    +
    +/* Styles for slides */
    +
    +.slides > article {
    +  font-family: 'Open Sans', Arial, sans-serif;
    +
    +  color: black;
    +  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
    +
    +  font-size: 26px;
    +  line-height: 36px;
    +
    +  letter-spacing: -1px;
    +}
    +
    +b {
    +  font-weight: 600;
    +}
    +
    +a {
    +  color: rgb(0, 102, 204);
    +  text-decoration: none;
    +}
    +a:visited {
    +  color: rgba(0, 102, 204, 0.75);
    +}
    +a:hover {
    +  color: black;
    +}
    +
    +p {
    +  margin: 0;
    +  padding: 0;
    +
    +  margin-top: 20px;
    +}
    +p:first-child {
    +  margin-top: 0;
    +}
    +
    +h1 {
    +  font-size: 60px;
    +  line-height: 60px;
    +
    +  padding: 0;
    +  margin: 0;
    +  margin-top: 200px;
    +  margin-bottom: 5px;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -3px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +h2 {
    +  font-size: 45px;
    +  line-height: 45px;
    +
    +  position: absolute;
    +  bottom: 150px;
    +
    +  padding: 0;
    +  margin: 0;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -2px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +h3 {
    +  font-size: 30px;
    +  line-height: 36px;
    +
    +  padding: 0;
    +  margin: 0;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -1px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +ul {
    +  margin: 0;
    +  padding: 0;
    +  margin-top: 20px;
    +  margin-left: 1.5em;
    +}
    +li {
    +  padding: 0;
    +  margin: 0 0 0.5em 0;
    +}
    +
    +div.code {
    +  padding: 5px 10px;
    +  margin-top: 20px;
    +  margin-bottom: 20px;
    +  overflow: hidden;
    +
    +  background: rgb(240, 240, 240);
    +  border: 1px solid rgb(224, 224, 224);
    +}
    +pre {
    +  margin: 0;
    +  padding: 0;
    +
    +  font-family: 'Droid Sans Mono', 'Courier New', monospace;
    +  font-size: 18px;
    +  line-height: 24px;
    +  letter-spacing: -1px;
    +
    +  color: black;
    +}
    +
    +pre.numbers span:before {
    +  content: attr(num);
    +  margin-right: 1em;
    +  display: inline-block;
    +}
    +
    +code {
    +  font-size: 95%;
    +  font-family: 'Droid Sans Mono', 'Courier New', monospace;
    +
    +  color: black;
    +}
    +
    +article > .image,
    +article > .video {
    +  text-align: center;
    +  margin-top: 40px;
    +}
    +
    +article.background {
    +  background-size: contain;
    +  background-repeat: round;
    +}
    +
    +table {
    +  width: 100%;
    +  border-collapse: collapse;
    +  margin-top: 40px;
    +}
    +th {
    +  font-weight: 600;
    +  text-align: left;
    +}
    +td,
    +th {
    +  border: 1px solid rgb(224, 224, 224);
    +  padding: 5px 10px;
    +  vertical-align: top;
    +}
    +
    +p.link {
    +  margin-left: 20px;
    +}
    +
    +.pagenumber {
    +  color: #8c8c8c;
    +  font-size: 75%;
    +  position: absolute;
    +  bottom: 0px;
    +  right: 10px;
    +}
    +
    +/* Code */
    +div.code {
    +  outline: 0px solid transparent;
    +}
    +div.playground {
    +  position: relative;
    +}
    +div.output {
    +  position: absolute;
    +  left: 50%;
    +  top: 50%;
    +  right: 40px;
    +  bottom: 40px;
    +  background: #202020;
    +  padding: 5px 10px;
    +  z-index: 2;
    +
    +  border-radius: 10px;
    +  -o-border-radius: 10px;
    +  -moz-border-radius: 10px;
    +  -webkit-border-radius: 10px;
    +}
    +div.output pre {
    +  margin: 0;
    +  padding: 0;
    +  background: none;
    +  border: none;
    +  width: 100%;
    +  height: 100%;
    +  overflow: auto;
    +}
    +div.output .stdout,
    +div.output pre {
    +  color: #e6e6e6;
    +}
    +div.output .stderr,
    +div.output .error {
    +  color: rgb(255, 200, 200);
    +}
    +div.output .system,
    +div.output .exit {
    +  color: rgb(255, 230, 120);
    +}
    +.buttons {
    +  position: relative;
    +  float: right;
    +  top: -60px;
    +  right: 10px;
    +}
    +div.output .buttons {
    +  position: absolute;
    +  float: none;
    +  top: auto;
    +  right: 5px;
    +  bottom: 5px;
    +}
    +
    +/* Presenter details */
    +.presenter {
    +  margin-top: 20px;
    +}
    +.presenter p,
    +.presenter .link {
    +  margin: 0;
    +  font-size: 28px;
    +  line-height: 1.2em;
    +}
    +
    +/* Output resize details */
    +.ui-resizable-handle {
    +  position: absolute;
    +}
    +.ui-resizable-n {
    +  cursor: n-resize;
    +  height: 7px;
    +  width: 100%;
    +  top: -5px;
    +  left: 0;
    +}
    +.ui-resizable-w {
    +  cursor: w-resize;
    +  width: 7px;
    +  left: -5px;
    +  top: 0;
    +  height: 100%;
    +}
    +.ui-resizable-nw {
    +  cursor: nw-resize;
    +  width: 9px;
    +  height: 9px;
    +  left: -5px;
    +  top: -5px;
    +}
    +iframe {
    +  border: none;
    +}
    +figcaption {
    +  color: #666;
    +  text-align: center;
    +  font-size: 0.75em;
    +}
    +
    +#help {
    +  font-family: 'Open Sans', Arial, sans-serif;
    +  text-align: center;
    +  color: white;
    +  background: #000;
    +  opacity: 0.5;
    +  position: fixed;
    +  bottom: 25px;
    +  left: 50px;
    +  right: 50px;
    +  padding: 20px;
    +
    +  border-radius: 10px;
    +  -o-border-radius: 10px;
    +  -moz-border-radius: 10px;
    +  -webkit-border-radius: 10px;
    +}
    diff --git a/2021/04/15/google/db-ranking-rdbms.png b/2021/04/15/google/db-ranking-rdbms.png
    new file mode 100644
    index 0000000..c05438a
    Binary files /dev/null and b/2021/04/15/google/db-ranking-rdbms.png differ
    diff --git a/2021/04/15/google/full-table-scan.png b/2021/04/15/google/full-table-scan.png
    new file mode 100644
    index 0000000..0c06af1
    Binary files /dev/null and b/2021/04/15/google/full-table-scan.png differ
    diff --git a/2021/04/15/google/gestalt-switch.jpg b/2021/04/15/google/gestalt-switch.jpg
    new file mode 100644
    index 0000000..9f9780a
    Binary files /dev/null and b/2021/04/15/google/gestalt-switch.jpg differ
    diff --git a/2021/04/15/google/get-on-journey.png b/2021/04/15/google/get-on-journey.png
    new file mode 100644
    index 0000000..7586163
    Binary files /dev/null and b/2021/04/15/google/get-on-journey.png differ
    diff --git a/2021/04/15/google/query-result-expectation.png b/2021/04/15/google/query-result-expectation.png
    new file mode 100644
    index 0000000..5410108
    Binary files /dev/null and b/2021/04/15/google/query-result-expectation.png differ
    diff --git a/2021/04/15/google/safari-cheetah.png b/2021/04/15/google/safari-cheetah.png
    new file mode 100644
    index 0000000..61849d0
    Binary files /dev/null and b/2021/04/15/google/safari-cheetah.png differ
    diff --git a/2021/04/15/google/shrug.png b/2021/04/15/google/shrug.png
    new file mode 100644
    index 0000000..3b1fac3
    Binary files /dev/null and b/2021/04/15/google/shrug.png differ
    diff --git a/2021/04/15/google/spanner.slide b/2021/04/15/google/spanner.slide
    new file mode 100644
    index 0000000..b1f9338
    --- /dev/null
    +++ b/2021/04/15/google/spanner.slide
    @@ -0,0 +1,340 @@
    +# Cloud Spanner Safari
    +A journey from the outside, into Cloud Spanner's underbelly
    +15 Apr 2021
    +Tags: databases,distributed-systems,debugging
    +
    +Emmanuel T Odeke
    +Orijtech, Inc.
    +emmanuel@orijtech.com
    +https://orijtech.com/
    +Observability, and infrastructure for high performance systems, and the cloud!
    +@odeke_et
    +
    +## Journey from outside, to the inside
    +
    + +## About myself +- Emmanuel T Odeke +- Building [Orijtech, Inc](https://orijtech.com/) +- Friend of Google: Contributor, Supplier, Google Cloud Partner for many years +- Help build many systems, projects, and work with a bunch of you +- Avid open source producer and consumer +- Designed and built Cloud Spanner for Django, Cloud Spanner for Ruby-on-Rails/ActiveRecord +- Led [OpenCensus](https://opencensus.io/) observability in many aspects from zero to successful merger +- Core contributor to the [Go programming language](https://golang.org/) +- Always learning, and enjoy solving problems! + +## What is this talk about? +- Dealt with Cloud Spanner's underbelly from the outside world +- Hinderances towards building with, and adopting Cloud Spanner +- Suggestions on how to grow +- Reality check +- Advisory and ideas for how to act upon identified needs + +## Narrative +- Cloud Spanner is Google's distributed relational, cloud native database, indefinitely scalable, highly performant, managed, battle tested +- Highest availability defying normal expectations of the CAP theorem +- Majority of the world uses legacy systems, mostly maintains code +- To grow Cloud Spanner, we need more and newer businesses to switch over +- To enable adoption, seemlessly integrate with existing code, reduce learning curve +- MARR (Minimum Acceptable Rate of Return) of using new databases must be much higher and sustainable, than just using older stable systems +- Switching over to any new database requires experience, determinism, features +- Knowledge gaps + +## Market share + +## Status quo +- Per [DB-Engines Ranking for popular Relational DBMS](https://db-engines.com/en/ranking/relational+dbms), Cloud Spanner is 51 out of 142 in rank, as of April 2021 +![](./db-ranking-rdbms.png) + +## Status quo +- At the top, we have OracleDB(42yr), MySQL(26yr), Microsoft SQL Server(32yr), PostgreSQL(25yr), IBM Db2(38yr), SQLite(30yr) +- Cloud Spanner was released February 2017 +- Doing great for a very young database +- To get to the top, plumb with both new and legacy systems, frameworks +- Make switch-over trivial +- Convenience, so that engineers can trivially convince their engineering management and finance departments to move to Cloud Spanner +- Cloud Spanner can definitely make it to Number 1! + +## Status quo +- Incumbents have dominated +- Scaling databases and reliability are pretty much rocket science +- Information and skills in this industry are very scarce +- [Sugu Sougoumarane](https://www.linkedin.com/in/sugu-sougoumarane-b9bb25/), CTO/co-founder of [PlanetScale Data](https://www.planetscale.com/) scaled YouTube's MySQL; was hired by Elon Musk for X.com, Paypal +- Can't expect every company to afford ninja dBAs and SRE teams +- Most applications are built using frameworks, ORMs: Django, Ruby-on-Rails, Spring +- Most code is maintained, more than newly written; hard to justify rewriting legacy code that works +- Dialect expertise means job pool is very limited in the already limited engineering talent pool +- Betting your business on a technology requires evidence of extraordinary results, incumbent mass adoption, buzz, leadership, copying from successes + +## Constraints for most companies +- Proof of concepts evolve into fully fledged products -- engineering decisions and stack have to be good from the start +- Technical expertise to run and scale databases +- Monetary constraints +- SRE problems +- Lack of expertise +- Every penny counts +- Least time, cost to setup/use -> creates more trust and easy decision making +- Simplicity is much better + +## Cloud Spanner as a business + +## Cloud Spanner strengths +- Engineering prowess, brand, and powerful backing of Google +- Amazing leadership and teams: genuinely focused on solving customer problems +- Cloud Spanner removes the need to become a dBA, or a scaling expert! +- Guts cost of running own databases: SRE nightmares, knowledge blackholes, server cost, observability, availability problems +- Scalability, libraries, integrations +- Very nice APIs to insert or update, named variables in statements, running transactions +- Very nice UI that's multi-purpose +- Backing of a top 3 cloud, and eco-system of other cloud products +- Cloud Spanner emulator introduced in mid 2020, allows for trials +- Ability to run on 1 node reduces cost massively, attractive to companies of all sizes + +## Increasing market share +- Google is successful for wholely owning information retrieval, making it trivial for every single business to find information and advertise their businesses +- Tackle the status quo and go into markets for which re-writing code afresh is impossible +- Analysis of the market: we listed out top ORMs by popularity +- Target: make Cloud Spanner trivially usable on popular ORMs +- Prior attempts at integrating with Rails and Django had failed as far as I know + +## Django +- Python and world's most popular web frameworks for the past ~16 years since July 15th, 2005 +- Django is [used by Instagram/Facebook ($727.32B), Tesla($626.98B), Spotify($57.11B), Dropbox($9.30B), Eventbrite($2.07B), YouTube($1.36T), Disqus($1.3B 2017), Washington Post($250M 2013), Robinhood($40B 2021), Pinterest($46.76B), DoorDash($47.09B), Postmates($2.65B 2020), GoDaddy($13.37B)](https://stackshare.io/django) +- Python is #3 as of [February 2021 on the TIOBE Index](https://www.tiobe.com/tiobe-index/python/) + +## ActiveRecord (Ruby-on-Rails) +- Ruby's most popular web framework, and one of the world's most influential web frameworks, MVC, since August 2004 +- Rails, ActiveRecord are [used by: Shopify, Airbnb, Twitter, Twitch, Instacart, Github, Accenture, Gitlab, Heroku, Intuit, Sendgrid/Twilio, Coinbase](https://stackshare.io/rails) +- Ruby is #14 as of [February 2021 on the TIOBE Index](https://www.tiobe.com/tiobe-index/ruby/) + +## Moonshots + +## Moonshots +- Audacious goals +- Meet businesses at home, bring Cloud Spanner to them +- Exisiting and future customers who'll feed into Google Cloud Platform +- Engineering leadership: Pritam, Shanika, Vikram, and others reached out, we collaborated +
    + +## Journey + +## Gestalt switch +
    + +## Lack of AUTO*INCREMENT +- Most of the world for the past 30 years has been using SQL databases that support AUTO*INCREMENT +- Sure, it is to avoid hot spotting in Cloud Spanner but patching to support for UUID generation was a whole hassle +- Patched support means customers have to re-write their sorting, breaks results: Hyrum's Law +- Cloud Spanner could have a mapping between assigned IDs and the actual UUIDs used as PRIMARY KEY +- Provide perhaps a UUID function that's used with DDL + +## Columns starting with "_" are not supported +- Makes it impossible for ORMs and frameworks to have special ordering/sorting routines nor orderings +- Django has `_order` but unfortunately can't be supported with Cloud Spanner + +## Lack of NUMERIC data type then +- The NUMERIC data type was added in late September 2020 (7 months ago) +- The remedy for this was just to store big nums as strings to avoid precision loss + +## ORDER BY RANDOM unsupported +- [Legacy apps have to rewrite their applications and remove random querying](https://github.com/googleapis/python-spanner-django/pull/432) +- This can be substituted by using [TABLESAMPLE](https://cloud.google.com/spanner/docs/query-syntax#tablesample_operator) combined with LIMIT N e.g. N=1, but TABLESAMPLE can return 0 rows if `percent` or `sample_size` don't match the population or if the ratios result in 0, so unreliable + +## Cannot type check on fields +- By the time many queries are being made, the original schema is unknown, yet there is no conditional to check or cast values +- Computations that yield FLOAT64 values cannot be assigned to INT64 columns, which limits querying and would have to redesign Cloud Spanner +- This is still an open problem with django-spanner e.g. [after integer division, which produces a float results, but that value can't be assigned to an integer column](https://github.com/googleapis/python-spanner-django/issues/331) + +## Hyper improvement with query optimizer +- Given this DDL + +```sql +CREATE TABLE Span ( + id STRING(16) NOT NULL, + trace_id STRING(32) NOT NULL, + parent_id STRING(16), + source_node STRING(32) NOT NULL, + start_time TIMESTAMP NOT NULL, + end_time TIMESTAMP, + saved_at TIMESTAMP OPTIONS (allow_commit_timestamp=true), + name STRING(MAX) NOT NULL, + kind INT64, + status_code INT64, + status_message STRING(MAX), + user_agent STRING(MAX), + CONSTRAINT FK_SpanNode FOREIGN KEY (source_node) REFERENCES Node(id), +) PRIMARY KEY (id, trace_id); +CREATE INDEX Span_EndTime ON Span (end_time) +CREATE INDEX Span_StartTime ON Span (start_time) +``` + +## Query optimizer improvement +```sql +SELECT DISTINCT(name) FROM Span WHERE start_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 120 SECOND) +``` + +
    + +## Hacky remedy +- Using FORCE_INDEX +- Avoid the full table scan that takes 16+ seconds +- Firstly infer that the output table names exist in the full table, else return an error +- Search through the target index, retrieve the respective PRIMARY KEY values and then search only by the trimmed value set using ID + +## Better remedy: more composite index: 16+sec -> 1.89sec +```sql +CREATE INDEX Span_SourceNode_Name_StartTime_EndTime_TraceID +ON Span ( + source_node, name, start_time, end_time, trace_id +) +``` +
    + +## Transactions can't mix DQL with DML +- Cannot mix Data Query Language (DQL) statements with Data Manipulation Language (DML) statements +- `SELECT * From Org1; DROP Table Org2` +- Made migrations insanely slow, can't be parallelized because of strict ordering +- Faux transaction whereby only abort DML iff prior DQL failed +- While the DQL is happening, can synchronize watches and then perform an exfiltration of data or modify tables concurrently and rename them, so that subsequent DML won't run, then rename it +- Ooh, INFORMATION_SCHEMA queries cannot also be performed in a READ-WRITE transaction :-( + +## Previously no advisory for expensive operations nor observability +- In March 2018 after brainstorming with Pritam, I wrote an article guiding folks for how to use [OpenCensus with Cloud Spanner in Java and Go](https://orijtech.medium.com/cloud-spanner-instrumented-by-opencensus-and-exported-to-stackdriver-6ed61ed6ab4e) +- It revealed cold start issues with CreateSession, and CreateTransaction, and also Cloud Spanner internally too after I sent a whole bunch of requests and triggered some alarms +- Caused a bit of an uproar within internal Spanner engineering, and even ropped in then engineering director Damian Reeves who personally replied and debugged issues +- Snap struggled with super high latency and didn't have any reasoning for why, I chimed in with data per [google-go-cloud/#207](https://github.com/googleapis/google-cloud-go/issues/1207) +- Why were customers guessing when we've got the most modern tools, and pioneered observability? Dapper, Census, OpenCensus all sparked multi-billion dollar industries +- Partly fixed with [Troubleshooting app latency with Cloud Spanner and OpenCensus](https://cloud.google.com/solutions/troubleshooting-app-latency-with-cloud-spanner-and-opencensus) + +## Column types can't be changed +- To change a data type, you have to create an entirely new table, transform/migrate all the data, then delete the prior table -- this is very inconvenient and can go on indefinitely, something businesses might get a bitter taste in their mouths about + +## No support for renaming tables and columns +- Makes Database schema migrations and renames impossible -- requires an expensive and laborious migration, can leave bitter tastes in one's mouth + +## Casting DATE to TIMESTAMP unexpectedly adds an hour +- Helped out by Andrew Byrne, who showed that we should always use "SELECT TIMESTAMP(date_column, 'GMT') FROM TBL" +- The solution works for that DATE->TIMESTAMP, but not when the ORM casts between TIMESTAMP->TIMESTAMP given that Cloud Spanner can't type check on field names + +## Lots of casting to do with IFNULL +- Lots of boiler plate needed for arithmetic functions when doing additions from dynamically typed languages +- Can't easily pass in parameters for addition lest: google.api_core.exceptions.InvalidArgument: 400 Operands of + cannot be literal + +## Foreign keys lack "ON DELETE CASCADE" +- Foreign keys were added to Cloud Spanner announced on Thursday 5th March 2020 +- Unfortunately can't delete related rows when a foreign key is deleted +- Can't support most ORMs +- Customers have to write their own specialized deletion routines, know which tables are associated +- Customers have to learn about using INFORMATION_SCHEMA +- Big surprise here, and requires Cloud Spanner expertise, to swap in for table interleaving but that's hacking now +- Due to lack of proper support for FOREIGN KEY so can't properly delete per [spanner-django/#313](https://github.com/googleapis/python-spanner-django/issues/313), nor for any other ORM + +## Impossible to compare TIMESTAMP & DATE +- Unfortunately this crashes queries, despite the ability to use `TIMESTAMP(date_column, "GMT")` +- At query time, the field type is unknown so this is an unsolved problem + +## Lack of SQL triggers +- The inability to intercept events due to lack of SQL triggers makes it a problem to react to events that make traditional SQL databases useful +- Also a feature that's been used for decades +- Perhaps a combination of PubSub + Cloud Functions? Cloud Run? + +## Inability to directly use Unicode as column names, without quoting values +- `SELECT (1) AS föö, 2 as umläut` fails +- Seemingly not easily available information on the docs website +- Required a pass over every single SQL query to backtick as per [spanner-django#374](https://github.com/googleapis/python-spanner-django/pull/374) +- Had to spend time debugging this failure on my own time + +## 10 second transaction timeouts are impossible to deal with, yet no easy transaction replay +- While the [10 second timeout](https://cloud.google.com/spanner/docs/reference/rest/v1/TransactionOptions#idle-transactions) is understandable for Cloud Spanner, in the rest of the world without those limits, trying to transfer directly is almost impossible +- Had to get my hands dirty and dive into the Python Cloud Spanner API and try to build this +- This setup delayed my project by months, and ran over my budget by a lot + +## Lack of support for proper transaction replay +- The Cloud Spanner Ruby, Python, Go clients lacked proper transaction replay which uses checksumming to validate replay +- Added for python-spanner, but seemingly not for Ruby and Go + +## Lack of an FAQ and specialized guides +- We need an FAQ for transparency that quickly informs one about what they need to know +- There is a guide for [PostgreSQL migration](https://cloud.google.com/spanner/docs/migrating-postgres-spanner) but that doesn't cover missing features and unknowns +- I had to ask a whole lot of questions, and get clarifications that roped in engineering leaders within the organization +- I've helped Googlers with Cloud Spanner, and built a previously almost impossible set of integrations, but objectively if I could struggle, that means the average builder is having it worse + +## Low administrative limits +- When building the various integrations, had to run multiple tests, hundreds every single day in parallel, 5 QPS is super duper low and wasted lots of time and money +- It took almost a week to get a response from the Cloud Spanner team to increase our limits for creating and tearing down databases +- Most customers won't be privileged to have direct relationships with Cloud Spanner engineering for help + +## Mutation limit per commit of 20,000 +- The number of mutations per commit being capped at 20,000 unfortunately doesn't mention the number of properties per mutation +- This means a bunch of insertions and updates will fail and give odd errors, unless customers manually do the calculations +- Such constraints make it very hard for companies without highly technical engineers to operate and fix problems +- This is a leaky abstraction beccause it exposes implementation details to users of APIs that are supposed to shield against complexity +- Solution: this work can be offloaded to every API client, just like in the Go BigTable API client + +## Statistical functions weren't supported for a long time +- Variance and Standard Deviation were not supported until June 2020 (way long after I was supposed to have completed developed) +- These were necessary for Django and Ruby-on-Rails users +- Lack of non-trivial statistical functions means composite queries can't be done with Cloud Spanner + +## Focusing on complexity of concepts as opposed to simplifying them +- Planet scalability, and the highest availability are amazing, but what does that mean for my aunt's pizza shop, what about for a bank, what about for Twitter? +- There are 2 kinds of READS with Cloud Spanner: Strong reads, Stale reads +- Zero advisory on when to use each, if you ask some Cloud Spanner team members when to use them in real life, but they can all explain what these are +- Everyone can explain why you need transactions, but somehow allow the fact that we can't run INFORMATION_SCHEMA queries in a READ-WRITE transaction +- Everyone understands why we need non-hotspotting PRIMARY KEYs, but why this couldn't be abstracted by the database +- Customers shouldn't even have to know about hotspotting: that should be specialized knowledge for performance engineering and Cloud Spanner should make customers so successful that this is handled by the backend + +## Dissonance between Client library maintainers and Cloud Spanner Engineering +- Getting answers for many problems encountered by asking the folks in charge of client libraries was very slow +- They are very overwhelmed, would have to relay questions to engineers, and that takes forever +- Huge burden expecting customers to intricately write their own engineering patches over the Cloud Spanner libraries to support lacking features +- Engineering mandate seemed to give direction that customers shouldn't keep transactions open for long, yet this is a case that Python experts within Google could build and remove the burden from customers +- Guides show how to get started, until you go in and have to swim in the deep all alone: I had to experiment and dig through Cloud Spanner technical docs myself, burnt through my time and money budgets + +## Migration tools are manual +- We've got [HarbourBridge](https://github.com/cloudspannerecosystem/harbourbridge) which is nice for a mid-size but non-production migration from PostgreSQL to Cloud Spanner +- Problem is that doing a database migration can take an indefinitely long time given that some apps can't be taken offline, nor shutdown +- No migration tools for MySQL nor for OracleDB, nor AuroraDB :-( +- No simulation tools to convince companies to switch over to Google tools and databases entirely, by sending over traffic to Cloud Spanner and executing queries then returning results and timing, directly comparing against their current systems +- Solving this kind of issue will rely on tools that intercept and sniff traffic, and have AST rewriters of sort -- credit to Louis Ryan with whom I discussed this idea on December 23rd 2019 at lunch in MP1 +- Less invasive tools + +## Migration tool: SQL sniffer -> AST rewrite -> Cloud Spanner +
    + +## Suggestions +- An aggressive approach towards building off the shelf applications, and using Cloud Spanner as customers would -- skin in the game +- We used this approach to test out that things worked alright for django-spanner and activerecord-spanner, and it revealed lots of oddities +- Offload functionality to the database server itself +- API clients should implement logic to handle replay, batching of transactions within limits, counting and splitting up mutations +- Fix low administrative limits -- it took a week +- Make it a sin to tell customers to perform complex work on their own +- FAQ with a bunch of listed caveats that developers can quickly ramp up to +- Skin in the game with teams that focus on building applications with customers and not just listing features that are lacking and letting customers suffer alone + +## Suggestions +- Look at [SQLCommenter](https://cloud.google.com/blog/topics/developers-practitioners/introducing-sqlcommenter-open-source-orm-auto-instrumentation-library) and [Cloud SQL insights](https://cloud.google.com/blog/products/databases/get-ahead-of-database-performance-issues-with-cloud-sql-insights) -- the ability to auto analyze performance for Cloud Spanner is a huge game changer that solves observability problems +- Thinking outside the box to ensure that the teams in charge of the API clients have enough attachment to engineering and can quickly answer questions +- Just like everyone somehow is on-call, customer success and API usability should be a tenet too +- Follow the mission/mantra of Google aggressively, apply that for databases and work relentlessly + +## What do you think? +
    + +## Shout outs to folks encountered on the journey +- Many folks on the Cloud Spanner team have been very helpful +- Pritam Shah, Vikram Manghani, John Corwin, Skylar Pottinger, Shanika Kuruppu, Ben Vandiver, Fuad Malikov, Youssef Barakat, Jiren Patel, Andrew Byrne, Damian Reeves, Xinhua Ji, Vikas Kedia, Di Xiao, Sailesh Krishnamurthy, Bala Chandrasekaran, Chris Kleinknecht, Mark Lu, Tim Graham, Nevin Heintze, Cliff Frey, Campbell Fraser and many more folks involved behind the scenes, plus the entire Cloud Spanner team + +## References +- [Cloud Spanner landing page]() +- [DB-Engines Ranking of Relational DBMS](https://db-engines.com/en/ranking/relational+dbms) +- [django-spanner](https://github.com/googleapis/python-spanner-django) +- [activerecord-spanner](https://github.com/googleapis/ruby-spanner-activerecord) +- [Cloud Spanner feature release notes](https://cloud.google.com/spanner/docs/release-notes) +- [PlanetScale Data:: hired by Elon Musk](https://techcrunch.com/2018/12/13/planetscale/) +- [Sugu Software Daily interview about Vitess scaling MySQL](https://www.softwaredaily.com/post/5afaad94a7d5220004cfd48f/vitess-scaling-mysql-with-sugu-sougoumarane) +- [Cloud Spanner types of reads](https://cloud.google.com/spanner/docs/reads) +- [PlanetScale Data](https://www.planetscale.com/) +- [Companies using Django per Stackshare](https://stackshare.io/django) +- [Companies using ActiveRecord per Stackshare](https://stackshare.io/django) diff --git a/2021/04/15/google/sqlsniff-AST-rewriter.png b/2021/04/15/google/sqlsniff-AST-rewriter.png new file mode 100644 index 0000000..aaad9ff Binary files /dev/null and b/2021/04/15/google/sqlsniff-AST-rewriter.png differ diff --git a/2021/12/02/amex/amex-hw-asm.png b/2021/12/02/amex/amex-hw-asm.png new file mode 100644 index 0000000..a8df245 Binary files /dev/null and b/2021/12/02/amex/amex-hw-asm.png differ diff --git a/2021/12/02/amex/cpuProfileOfCode.jpg b/2021/12/02/amex/cpuProfileOfCode.jpg new file mode 100644 index 0000000..6ea5efe Binary files /dev/null and b/2021/12/02/amex/cpuProfileOfCode.jpg differ diff --git a/2021/12/02/amex/enable_http2.go b/2021/12/02/amex/enable_http2.go new file mode 100644 index 0000000..307065c --- /dev/null +++ b/2021/12/02/amex/enable_http2.go @@ -0,0 +1,19 @@ +package main + +func main() { + ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello, %s", r.Proto) + })) + ts.EnableHTTP2 = true + ts.StartTLS() + defer ts.Close() + + res, err := ts.Client().Get(ts.URL) + if err != nil { + log.Fatal(err) + } + greeting, err := ioutil.ReadAll(res.Body) + res.Body.Close() + if err != nil { panic(err) } + println(string(greeting)) +} diff --git a/2021/12/02/amex/fmt-Bop.png b/2021/12/02/amex/fmt-Bop.png new file mode 100644 index 0000000..60605b6 Binary files /dev/null and b/2021/12/02/amex/fmt-Bop.png differ diff --git a/2021/12/02/amex/fmt-nop.png b/2021/12/02/amex/fmt-nop.png new file mode 100644 index 0000000..bd37827 Binary files /dev/null and b/2021/12/02/amex/fmt-nop.png differ diff --git a/2021/12/02/amex/fmt-speed.png b/2021/12/02/amex/fmt-speed.png new file mode 100644 index 0000000..339017b Binary files /dev/null and b/2021/12/02/amex/fmt-speed.png differ diff --git a/2021/12/02/amex/fmt-timeop.png b/2021/12/02/amex/fmt-timeop.png new file mode 100644 index 0000000..c56e252 Binary files /dev/null and b/2021/12/02/amex/fmt-timeop.png differ diff --git a/2021/12/02/amex/geniusOfAlexander.jpg b/2021/12/02/amex/geniusOfAlexander.jpg new file mode 100644 index 0000000..c1719cf Binary files /dev/null and b/2021/12/02/amex/geniusOfAlexander.jpg differ diff --git a/2021/12/02/amex/go_machine_guides.htm b/2021/12/02/amex/go_machine_guides.htm new file mode 100644 index 0000000..fdd8535 --- /dev/null +++ b/2021/12/02/amex/go_machine_guides.htm @@ -0,0 +1,870 @@ + + + + Go, as the machine guides + + + + + + + + + + + +
    + +
    +

    Go, as the machine guides

    + + + +
    + + +

    + Emmanuel T Odeke +

    + + + +

    + Orijtech, Inc. +

    + + + +

    + Thu 2 Dec 2021 +

    + + +
    + +
    + + + +
    + +

    Go, as the machine guides

    + + 2 +
    + + + +
    + +

    Let the machine guide you

    +
      +
    • "Genius of Alexander, Marie Louise Elisabeth Vigée-Lebrun, 1814"
    • +
    +
    + + 3 +
    + + + +
    + +

    About this talk

    +
      +
    • Dissecting some common scenarios
    • +
    • Empowering you with productivity and dexterity with the Go programming language
    • +
    • High performance engineering tools and tips
    • +
    • Digging deeper than the surface shows
    • +
    • Pragmatic problem solving
    • +
    • Real world experiences and examples
    • +
    • Let the machine guide you!
    • +
    + + + 4 +
    + + + +
    + +

    About myself

    +
      +
    • Emmanuel T Odeke
    • +
    • Building Orijtech, Inc
    • +
    • Enjoy learning and solving problems; I am mostly self taught
    • +
    • Always learning
    • +
    • Avid open source producer and consumer
    • +
    • Core contributor and leader on the Go programming language
    • +
    • Core contributor and leader on OpenCensus and OpenTelemetry
    • +
    • Always learning, and enjoy solving problems!
    • +
    • Building critical and high performance software engineering tools like Go, static analyzers, CI/CD infrastructure, databases, observability infrastructure, security infrastructure
    • +
    + + + 5 +
    + + + +
    + +

    About Go

    +
      +
    • The Go programming language is the undisputed language of the cloud
    • +
    • 30+% of the Fortune 100 use Go, including American Express
    • +
    • Modern, simple, maintainable, very fast, robust, performant, easy to learn and teach
    • +
    • Highly productive language
    • +
    • Been public for 12 years since (November 8th 2009) after release from Google
    • +
    • Very smart people who deeply care about developer productivity & efficiency
    • +
    • Mature language collaboratively contributed to by the community
    • +
    • It has hidden gems that we should all wield
    • +
    + + + 6 +
    + + + +
    + +

    Go as the machine guides

    +
      +
    • What's odd about this code? You encounter it in a code review
    • +
    + +
    +
    // SanitizeGenesisBalances sorts addresses and coin sets.
    +func SanitizeGenesisBalances(balances []Balance) []Balance {
    +    sort.Slice(balances, func(i, j int) bool {
    +        addr1, _ := sdk.AccAddressFromBech32(balances[i].Address)
    +        addr2, _ := sdk.AccAddressFromBech32(balances[j].Address)
    +        return bytes.Compare(addr1.Bytes(), addr2.Bytes()) < 0
    +    })
    +
    +    for _, balance := range balances {
    +        balance.Coins = balance.Coins.Sort()
    +    }
    +
    +    return balances
    +}
    +
    +
    +
      +
    • You could say perhaps sdk.AccAddressFromBech32 returns an error that's ignored?
    • +
    + + + 7 +
    + + + +
    + +

    How do we know?

    + + 8 +
    + + + +
    + +

    How do we know?

    +
      +
    • We build upon layers of unknowns and code we can't all examine
    • +
    • We can't fix what we can't measure nor perceive
    • +
    • Guess work can't cut it to find needles in haystacks
    • +
    • The entropy/number of chaotic states is indefinite so we need a way to get to answers really fast
    • +
    + + + 9 +
    + + + +
    + +

    Responses

    +
      +
    • Context matters
    • +
    • Should it be of concern?
    • +
    • If the code is in a hot loop, it matters
    • +
    • If it isn't significantly called, it doesn't matter
    • +
    • How can we figure out if it slow? How could we examine and fix these problems?
    • +
    • How important is it?
    • +
    • CPU and RAM profiling...pprof to the rescue
    • +
    • We should use it to non-invasively examine the states of our programs...
    • +
    + + + 10 +
    + + + +
    + +

    CPU and RAM Profiling

    +
      +
    • Modern CPUs have frequencies of >2.1Ghz frequency -- they run 2.1 billion times a second
    • +
    • Sampling profiling stops the CPU 100 times a second and inquires about the program counter plus state of the heap
    • +
    • Guiding light that'll show you where you've expended resources
    • +
    • No need to guess what is going on
    • +
    • pprof was designed and built in C++, at Google in about 2001 by the esteemed Sanjay Ghemawat
    • +
    + + + 11 +
    + + + +
    + +

    Back to that seemingly innocent code...

    +
      +
    • What if I told you that this code caused issues for a $150+B market cap ecosystem?
    • +
    + +
    +
    // SanitizeGenesisBalances sorts addresses and coin sets.
    +func SanitizeGenesisBalances(balances []Balance) []Balance {
    +    sort.Slice(balances, func(i, j int) bool {
    +        addr1, _ := sdk.AccAddressFromBech32(balances[i].Address)
    +        addr2, _ := sdk.AccAddressFromBech32(balances[j].Address)
    +        return bytes.Compare(addr1.Bytes(), addr2.Bytes()) < 0
    +    })
    +
    +    for _, balance := range balances {
    +        balance.Coins = balance.Coins.Sort()
    +    }
    +
    +    return balances
    +}
    +
    +
    + + + 12 +
    + + + +
    + +

    Profile of the code in context

    +
    + + 13 +
    + + + +
    + +

    What was up with that code?

    +
      +
    • The number of accounts was large e.g. 100,000+ accounts
    • +
    • Invoked sort.Slice (Quicksort in Go) which is a O(n^2) algorithm
    • +
    • Performed heavy work in a loop and discarded address parsing
    • +
    • Also some unnecessary work and unnecessary byteslice->string comparisons when looking up maps
    • +
    • The compound effect was super slow code that had a toll on launches for these folks
    • +
    • Oops
    • +
    + + + 14 +
    + + + +
    + +

    Remedy

    +
      +
    • After exorcising the problem, it showed that we needed to only parse addresses once, then use the already memoized values
    • +
    • Applying map zero byteslice->string conversion in a map look up radically reduced expenses in every dimension by more than 90%
    • +
    • CPU time reduced by -92.46%
    • +
    • Allocation counts per operation reduced by -93.76%
    • +
    • Allocated bytes per operation reduced by -93.76%
    • +
    • Very happy customers!
    • +
    + + + 15 +
    + + + + + + + +
    + +

    The state of your HTTP2 servers in Go

    + + 17 +
    + + + +
    + +

    Debugging HTTP servers (HTTP/2)

    +
      +
    • HTTP/2 is quite popular, https://americanexpress.com uses it!
    • +
    • Almost all consumer businesses are accessible via a website
    • +
    • Go has a mature set of libraries for networking net/* and net/http/*
    • +
    + +
    +
    package main
    +
    +func main() {
    +    ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    +        fmt.Fprintf(w, "Hello, %s", r.Proto)
    +    }))
    +    ts.EnableHTTP2 = true
    +    ts.StartTLS()
    +    defer ts.Close()
    +
    +    res, err := ts.Client().Get(ts.URL)
    +    if err != nil {
    +        log.Fatal(err)
    +    }
    +    greeting, err := ioutil.ReadAll(res.Body)
    +    res.Body.Close()
    +    if err != nil { panic(err) }
    +        println(string(greeting))
    +}
    +
    +
    + + + 18 +
    + + + +
    + +

    net/http GODEBUG=http2debug=2

    +
      +
    • Prime example was finding an insidious bug in Google Cloud Storage's new storage metadata engine that was written in C++ in June 2019
    • +
    • Bug was "storage: fix TestIntegration_Objects": issue #1482
    • +
    • We couldn't blame cosmic rays for some of the requests crashing with a 5XX status code and non-uniformly
    • +
    • I used GODEBUG=http2debug=2 and sent 10s of thousands of requests then tallied up the failures and discovered oddities
    • +
    • Passing metadata JSON of {"contentType": null} caused the new production C++ backend to crash, it hadn't been properly fuzzed nor tested; a static analyzer could have caught this
    • +
    • Caused a production freeze at Google for a while
    • +
    + + + 19 +
    + + + +
    + +

    Wholistic state of your HTTP and gRPC services?

    + + 20 +
    + + + +
    + +

    Observability

    +
      +
    • Ability to examine the states of your system
    • +
    • Introspection of programs requires intricate tools and methods
    • +
    • Tracing and metrics are user defined mechanisms that get added to applications and require context propagation as systems talk to each other
    • +
    • OpenCensus->OpenTelemetry
    • +
    • What happens when you can't edit the source?
    • +
    • Usually there will be instrumented frameworks, but you might need to import code or manually edit code
    • +
    • Some code requires intricate edits, which at times might not be possible
    • +
    • Let the machine guide you
    • +
    + + + 21 +
    + + + +
    + +

    Go performance tips

    + + 22 +
    + + + +
    + +

    Continuous benchmarking

    +
      +
    • Code changes across small parts of code can build up into something much more
    • +
    • Without knowing how your change affects general parts of your code, you are flying blind
    • +
    • Orijtech Inc produced the world's s first continuous benchmarking product, firstly focused on the Go programming language
    • +
    + + + 23 +
    + + + +
    + +

    map[string(byteslice)] to retrieve values

    +
      +
    • For maps, the keys are required to be immutable and hashable
    • +
    • When retrieving a value, directly perform the byteslice->string conversion when retrieving the value. The Go compiler +recognizes this pattern as a read-only operation and will perform the reflect.StringHeader retrieval for you
    • +
    + +
    +
    package main
    +
    +func main() {
    +    m := map[string]int{"ten": 10}
    +    ten := []byte("ten")
    +    // Expensive way.
    +    key := string(ten)
    +    println(m[key])
    +
    +    // Cheap way.
    +    println(m[string(ten)])
    +}
    +
    +
    + + + 24 +
    + + + +
    + +

    map clearing idiom

    +
      +
    • Simply use a loop that iterates over keys & invoke delete(m, key)
    • +
    + +
    +
    package main
    +
    +func clearNonFast(m map[string]int) {
    +    keys := make([]string, 0, len(m))
    +    for key := range m {
    +        keys = append(keys, key)
    +    }
    +
    +    // Do something with keys.
    +    // _ = keys
    +    for _, key := range keys {
    +        delete(m, key)
    +    }
    +}
    +
    +func clearFast(m map[string]int) {
    +    for key := range m {
    +        delete(m, key)
    +    }
    +}
    +
    +
    + + + 25 +
    + + + + + + + +
    + +

    Unsafe/reflect

    +
      +
    • Importing "unsafe" in your Go programs comes with a banner warning "Packages that import unsafe may be non-portable and are not protected by the Go 1 compatibility guidelines."
    • +
    • However, if say you have hot code that allocates a byte slice and you need to parse its string value, so it'll never be referenced out of that section
    • +
    • unsafe.Pointer and reflect.SliceHeader/reflect.StringHeader come in
    • +
    • Actual case for further speeding up American Express' "simplemli" per americanexpress/simplemli/pull#4
    • +
    • Reduction results in elimination of allocations in Decode.MLIA4E
    • +
    + + + 27 +
    + + + +
    + +

    Byteslice <-> string conversion

    + +
    +
    package main
    +
    +import (
    +    "fmt"
    +    "reflect"
    +    "unsafe"
    +)
    +
    +func unsafeByteSliceToStr(b []byte) string {
    +    return *(*string)(unsafe.Pointer(&b))
    +}
    +
    +func unsafeStrToByteSlice(s string) (b []byte) {
    +    hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b))
    +    hdr.Cap = len(s)
    +    hdr.Len = len(s)
    +    hdr.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
    +    return b
    +}
    +
    +func main() {
    +    fmt.Printf("%q\n", unsafeByteSliceToStr([]byte("string")))
    +    fmt.Printf("% x\n", unsafeStrToByteSlice("string"))
    +}
    +
    +
    + + + 28 +
    + + + + + + + +
    + +

    Unintended byteslice->string conversion penalty with fmt.*printf

    +
      +
    • Some times when using fmt.*printf e.g. fmt.Sprintf, if any of the arguments are byteslices we might get tempted to convert it firstly to a string
    • +
    • string(byteslice) then invoke fmt.Sprintf
    • +
    • fmt.Printf("This is my name: %s\n", string(nameInByteSlice))
    • +
    • Expensive and unnecessary, please use the format specifier "%s" or "%q" which will handle the conversion to a string smartly
    • +
    • fmt.Printf("This is my name: %s\n", nameInByteSlice)
    • +
    • What is the impact of this change?
    • +
    • Lo and behold, benchmarking to the rescue so we don't have to guess
    • +
    • Please see https://dashboard.bencher.orijtech.com/benchmark/3245b8e4bbbd44a597480319aaa4b9fe
    • +
    + + + 30 +
    + + + +
    + +

    Letting fmt.*printf "%s" handle its conversions

    +
    +
    + + 31 +
    + + + +
    + +

    Letting fmt.*printf "%s" handle its conversions

    +
    +
    + + 32 +
    + + + +
    + +

    Scalable and more secure software development guided by the machine?

    + + 33 +
    + + + +
    + +

    Static analyzers

    +
      +
    • Before code is run, examine the Abstract Syntax Tree (AST) and by rules, match patterns that are malformed or could cause insidious bugs
    • +
    • These help catch insidious bugs that could otherwise cause mayhem, runtime issues, crashes etc
    • +
    • Developer productivity and correctness are facets of high performance engineering
    • +
    • Just run go test or add staticcheck to your pipelines to run static analyzers
    • +
    • Orijtech Inc contributes static analyzers to the Go programming language and we've also got many more brewing
    • +
    • structslop, httperroyzer, sigchanyzer, tickeryzer, testinggoroutine, strconvparseuinterroryzer etc...
    • +
    + + + 34 +
    + + + +
    + +

    Internal states of the Go runtime?

    + + 35 +
    + + + +
    + +

    runtime/trace

    +
      +
    • runtime/trace provides facilities for generating traces to use with the Go trace executioner
    • +
    • Prime example, in July 2019, the late Michael T Jones reported that a particular test that checked the number of threads to have os file reads was failing
    • +
    • Everyone on the Go development mailing list was puzzled and didn't know what was going on
    • +
    • While on a long haul flight back to California on August 29th 2019, I started investigating; as soon as I landed, rushed to my office whiteboard and modelled scenarios
    • +
    • Emailed MTJ and created custom code to collect runtime traces which indeed showed that there was something fishy going on and that a thread was taken for every read
    • +
    • I showed my findings at golang.org/issue/32326
    • +
    + + + 36 +
    + + + +
    + +

    Findings

    +
      +
    • Serious bug against expectations of the Go runtime scheduler and runtime poller
    • +
    +
    +
      +
    • In runtime/sys_darwing.go, when making a syscall, there was a typo to use entersyscallblock() instead of entersyscall
    • +
    • Cause confirmed & fixed by Minux Ma; bug shipped in Go1.12 and found in Go1.13
    • +
    + + + 37 +
    + + + +
    + +

    Scheduler and Garbage collector states

    +
      +
    • You can learn more by visiting the Go runtime package's docs
    • +
    • You can see what the scheduler is upto by passing GODEBUG=scheddetail=1,schedtrace=X ./go_binary where X is a value in milliseconds
    • +
    + + + 38 +
    + + + +
    + +

    Examining the generated assembly

    + + 39 +
    + + + +
    + +

    Go Assembly examination

    +
      +
    • To examine generated code if you really want to dive in, please use -S when building your Go binaries
    • +
    • What does our "Hello, World!" produce?
    • +
    • When we run: go build -o hw.s -gcflags="-S" helloworld.go
    • +
    + +
    +
    package main
    +
    +func main() {
    +    println("An honor to be at American Express.. Don't live life without it!")
    +}
    +
    +
    + + + 40 +
    + + + +
    + +

    Hello world Assembly

    +
    + + 41 +
    + + + +
    + +

    Toolbox assembly

    + + 42 +
    + + + +
    + +

    Summing it all up

    +
      +
    • With the arsenal of knowledge that we've garnered here, here is our summary
    • +
    • Add observability to your toolbox -- Jaeger, Zipkin, Prometheus, Expedia's Haystack are great open source alternatives, or a great APM provider
    • +
    • OpenCensus, OpenTelemetry to track higher level states of the system such as requests going into your application's server, monitoring to alert on traffic spikes
    • +
    • GODEBUG=http2debug=2 to debug your net/http HTTP/2 services
    • +
    • pprof and continuous profiling to dig deep into fine grained states of how your program behaves
    • +
    • runtime/trace and the Chrome trace viewer using go tool trace file to introspect the state of the Go scheduler
    • +
    • Add benchmarks to your code wholistically; adopt continuous benchmarking or visit Orijtech's own Bencher https://bencher.orijtech.com/
    • +
    • Use GODEBUG=scheddetail=1,schedtrace=X
    • +
    • Assembly examination
    • +
    + + + 43 +
    + + + + + + + + + +
    + + + + + + + + + + + \ No newline at end of file diff --git a/2021/12/02/amex/go_machine_guides_files/amex-hw-asm.png b/2021/12/02/amex/go_machine_guides_files/amex-hw-asm.png new file mode 100644 index 0000000..a8df245 Binary files /dev/null and b/2021/12/02/amex/go_machine_guides_files/amex-hw-asm.png differ diff --git a/2021/12/02/amex/go_machine_guides_files/cpuProfileOfCode.jpg b/2021/12/02/amex/go_machine_guides_files/cpuProfileOfCode.jpg new file mode 100644 index 0000000..6ea5efe Binary files /dev/null and b/2021/12/02/amex/go_machine_guides_files/cpuProfileOfCode.jpg differ diff --git a/2021/12/02/amex/go_machine_guides_files/css b/2021/12/02/amex/go_machine_guides_files/css new file mode 100644 index 0000000..74f0a8e --- /dev/null +++ b/2021/12/02/amex/go_machine_guides_files/css @@ -0,0 +1,296 @@ +/* latin */ +@font-face { + font-family: 'Droid Sans Mono'; + font-style: normal; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/droidsansmono/v14/6NUO8FuJNQ2MbkrZ5-J8lKFrp7pRef2rUGIW9g.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtE6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWvU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWu06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWt06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuU6FxZCJgg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtE6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWvU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWu06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWt06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuU6FxZCJgg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-mu0SC55I.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v27/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-mu0SC55I.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/2021/12/02/amex/go_machine_guides_files/fmt-Bop.png b/2021/12/02/amex/go_machine_guides_files/fmt-Bop.png new file mode 100644 index 0000000..60605b6 Binary files /dev/null and b/2021/12/02/amex/go_machine_guides_files/fmt-Bop.png differ diff --git a/2021/12/02/amex/go_machine_guides_files/fmt-nop.png b/2021/12/02/amex/go_machine_guides_files/fmt-nop.png new file mode 100644 index 0000000..bd37827 Binary files /dev/null and b/2021/12/02/amex/go_machine_guides_files/fmt-nop.png differ diff --git a/2021/12/02/amex/go_machine_guides_files/fmt-speed.png b/2021/12/02/amex/go_machine_guides_files/fmt-speed.png new file mode 100644 index 0000000..339017b Binary files /dev/null and b/2021/12/02/amex/go_machine_guides_files/fmt-speed.png differ diff --git a/2021/12/02/amex/go_machine_guides_files/fmt-timeop.png b/2021/12/02/amex/go_machine_guides_files/fmt-timeop.png new file mode 100644 index 0000000..c56e252 Binary files /dev/null and b/2021/12/02/amex/go_machine_guides_files/fmt-timeop.png differ diff --git a/2021/12/02/amex/go_machine_guides_files/geniusOfAlexander.jpg b/2021/12/02/amex/go_machine_guides_files/geniusOfAlexander.jpg new file mode 100644 index 0000000..c1719cf Binary files /dev/null and b/2021/12/02/amex/go_machine_guides_files/geniusOfAlexander.jpg differ diff --git a/2021/12/02/amex/go_machine_guides_files/mapsdeletion-verdict-results.png b/2021/12/02/amex/go_machine_guides_files/mapsdeletion-verdict-results.png new file mode 100644 index 0000000..93282ff Binary files /dev/null and b/2021/12/02/amex/go_machine_guides_files/mapsdeletion-verdict-results.png differ diff --git a/2021/12/02/amex/go_machine_guides_files/play.js b/2021/12/02/amex/go_machine_guides_files/play.js new file mode 100644 index 0000000..d62d2bf --- /dev/null +++ b/2021/12/02/amex/go_machine_guides_files/play.js @@ -0,0 +1,715 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
    a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
    t
    ",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
    ",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
    ",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

    ",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
    ","
    "]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
    ").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);/*! jQuery UI - v1.10.2 - 2013-03-20 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.resizable.js +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
    ",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("
    ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
    "),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css("left")),n=t(this.helper.css("top")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===n&&(e.left=t.left+(s.width-e.width),e.top=null),"nw"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidthe.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
    "),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=e(this).data("ui-resizable"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e(["Top","Right","Left","Bottom"]).each(function(e,n){s[e]=t(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,"left")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery);// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +In the absence of any formal way to specify interfaces in JavaScript, +here's a skeleton implementation of a playground transport. + + function Transport() { + // Set up any transport state (eg, make a websocket connection). + return { + Run: function(body, output, options) { + // Compile and run the program 'body' with 'options'. + // Call the 'output' callback to display program output. + return { + Kill: function() { + // Kill the running program. + } + }; + } + }; + } + + // The output callback is called multiple times, and each time it is + // passed an object of this form. + var write = { + Kind: 'string', // 'start', 'stdout', 'stderr', 'end' + Body: 'string' // content of write or end status message + } + + // The first call must be of Kind 'start' with no body. + // Subsequent calls may be of Kind 'stdout' or 'stderr' + // and must have a non-null Body string. + // The final call should be of Kind 'end' with an optional + // Body string, signifying a failure ("killed", for example). + + // The output callback must be of this form. + // See PlaygroundOutput (below) for an implementation. + function outputCallback(write) { + } +*/ + +// HTTPTransport is the default transport. +// enableVet enables running vet if a program was compiled and ran successfully. +// If vet returned any errors, display them before the output of a program. +function HTTPTransport(enableVet) { + 'use strict'; + + function playback(output, data) { + // Backwards compatibility: default values do not affect the output. + var events = data.Events || []; + var errors = data.Errors || ''; + var status = data.Status || 0; + var isTest = data.IsTest || false; + var testsFailed = data.TestsFailed || 0; + + var timeout; + output({ Kind: 'start' }); + function next() { + if (!events || events.length === 0) { + if (isTest) { + if (testsFailed > 0) { + output({ + Kind: 'system', + Body: + '\n' + + testsFailed + + ' test' + + (testsFailed > 1 ? 's' : '') + + ' failed.', + }); + } else { + output({ Kind: 'system', Body: '\nAll tests passed.' }); + } + } else { + if (status > 0) { + output({ Kind: 'end', Body: 'status ' + status + '.' }); + } else { + if (errors !== '') { + // errors are displayed only in the case of timeout. + output({ Kind: 'end', Body: errors + '.' }); + } else { + output({ Kind: 'end' }); + } + } + } + return; + } + var e = events.shift(); + if (e.Delay === 0) { + output({ Kind: e.Kind, Body: e.Message }); + next(); + return; + } + timeout = setTimeout(function() { + output({ Kind: e.Kind, Body: e.Message }); + next(); + }, e.Delay / 1000000); + } + next(); + return { + Stop: function() { + clearTimeout(timeout); + }, + }; + } + + function error(output, msg) { + output({ Kind: 'start' }); + output({ Kind: 'stderr', Body: msg }); + output({ Kind: 'end' }); + } + + function buildFailed(output, msg) { + output({ Kind: 'start' }); + output({ Kind: 'stderr', Body: msg }); + output({ Kind: 'system', Body: '\nGo build failed.' }); + } + + var seq = 0; + return { + Run: function(body, output, options) { + seq++; + var cur = seq; + var playing; + $.ajax('/compile', { + type: 'POST', + data: { version: 2, body: body, withVet: enableVet }, + dataType: 'json', + success: function(data) { + if (seq != cur) return; + if (!data) return; + if (playing != null) playing.Stop(); + if (data.Errors) { + if (data.Errors === 'process took too long') { + // Playback the output that was captured before the timeout. + playing = playback(output, data); + } else { + buildFailed(output, data.Errors); + } + return; + } + if (!data.Events) { + data.Events = []; + } + if (data.VetErrors) { + // Inject errors from the vet as the first events in the output. + data.Events.unshift({ + Message: 'Go vet exited.\n\n', + Kind: 'system', + Delay: 0, + }); + data.Events.unshift({ + Message: data.VetErrors, + Kind: 'stderr', + Delay: 0, + }); + } + + if (!enableVet || data.VetOK || data.VetErrors) { + playing = playback(output, data); + return; + } + + // In case the server support doesn't support + // compile+vet in same request signaled by the + // 'withVet' parameter above, also try the old way. + // TODO: remove this when it falls out of use. + // It is 2019-05-13 now. + $.ajax('/vet', { + data: { body: body }, + type: 'POST', + dataType: 'json', + success: function(dataVet) { + if (dataVet.Errors) { + // inject errors from the vet as the first events in the output + data.Events.unshift({ + Message: 'Go vet exited.\n\n', + Kind: 'system', + Delay: 0, + }); + data.Events.unshift({ + Message: dataVet.Errors, + Kind: 'stderr', + Delay: 0, + }); + } + playing = playback(output, data); + }, + error: function() { + playing = playback(output, data); + }, + }); + }, + error: function() { + error(output, 'Error communicating with remote server.'); + }, + }); + return { + Kill: function() { + if (playing != null) playing.Stop(); + output({ Kind: 'end', Body: 'killed' }); + }, + }; + }, + }; +} + +function SocketTransport() { + 'use strict'; + + var id = 0; + var outputs = {}; + var started = {}; + var websocket; + if (window.location.protocol == 'http:') { + websocket = new WebSocket('ws://' + window.location.host + '/socket'); + } else if (window.location.protocol == 'https:') { + websocket = new WebSocket('wss://' + window.location.host + '/socket'); + } + + websocket.onclose = function() { + console.log('websocket connection closed'); + }; + + websocket.onmessage = function(e) { + var m = JSON.parse(e.data); + var output = outputs[m.Id]; + if (output === null) return; + if (!started[m.Id]) { + output({ Kind: 'start' }); + started[m.Id] = true; + } + output({ Kind: m.Kind, Body: m.Body }); + }; + + function send(m) { + websocket.send(JSON.stringify(m)); + } + + return { + Run: function(body, output, options) { + var thisID = id + ''; + id++; + outputs[thisID] = output; + send({ Id: thisID, Kind: 'run', Body: body, Options: options }); + return { + Kill: function() { + send({ Id: thisID, Kind: 'kill' }); + }, + }; + }, + }; +} + +function PlaygroundOutput(el) { + 'use strict'; + + return function(write) { + if (write.Kind == 'start') { + el.innerHTML = ''; + return; + } + + var cl = 'system'; + if (write.Kind == 'stdout' || write.Kind == 'stderr') cl = write.Kind; + + var m = write.Body; + if (write.Kind == 'end') { + m = '\nProgram exited' + (m ? ': ' + m : '.'); + } + + if (m.indexOf('IMAGE:') === 0) { + // TODO(adg): buffer all writes before creating image + var url = 'data:image/png;base64,' + m.substr(6); + var img = document.createElement('img'); + img.src = url; + el.appendChild(img); + return; + } + + // ^L clears the screen. + var s = m.split('\x0c'); + if (s.length > 1) { + el.innerHTML = ''; + m = s.pop(); + } + + m = m.replace(/&/g, '&'); + m = m.replace(//g, '>'); + + var needScroll = el.scrollTop + el.offsetHeight == el.scrollHeight; + + var span = document.createElement('span'); + span.className = cl; + span.innerHTML = m; + el.appendChild(span); + + if (needScroll) el.scrollTop = el.scrollHeight - el.offsetHeight; + }; +} + +(function() { + function lineHighlight(error) { + var regex = /prog.go:([0-9]+)/g; + var r = regex.exec(error); + while (r) { + $('.lines div') + .eq(r[1] - 1) + .addClass('lineerror'); + r = regex.exec(error); + } + } + function highlightOutput(wrappedOutput) { + return function(write) { + if (write.Body) lineHighlight(write.Body); + wrappedOutput(write); + }; + } + function lineClear() { + $('.lineerror').removeClass('lineerror'); + } + + // opts is an object with these keys + // codeEl - code editor element + // outputEl - program output element + // runEl - run button element + // fmtEl - fmt button element (optional) + // fmtImportEl - fmt "imports" checkbox element (optional) + // shareEl - share button element (optional) + // shareURLEl - share URL text input element (optional) + // shareRedirect - base URL to redirect to on share (optional) + // toysEl - toys select element (optional) + // enableHistory - enable using HTML5 history API (optional) + // transport - playground transport to use (default is HTTPTransport) + // enableShortcuts - whether to enable shortcuts (Ctrl+S/Cmd+S to save) (default is false) + // enableVet - enable running vet and displaying its errors + function playground(opts) { + var code = $(opts.codeEl); + var transport = opts['transport'] || new HTTPTransport(opts['enableVet']); + var running; + + // autoindent helpers. + function insertTabs(n) { + // find the selection start and end + var start = code[0].selectionStart; + var end = code[0].selectionEnd; + // split the textarea content into two, and insert n tabs + var v = code[0].value; + var u = v.substr(0, start); + for (var i = 0; i < n; i++) { + u += '\t'; + } + u += v.substr(end); + // set revised content + code[0].value = u; + // reset caret position after inserted tabs + code[0].selectionStart = start + n; + code[0].selectionEnd = start + n; + } + function autoindent(el) { + var curpos = el.selectionStart; + var tabs = 0; + while (curpos > 0) { + curpos--; + if (el.value[curpos] == '\t') { + tabs++; + } else if (tabs > 0 || el.value[curpos] == '\n') { + break; + } + } + setTimeout(function() { + insertTabs(tabs); + }, 1); + } + + // NOTE(cbro): e is a jQuery event, not a DOM event. + function handleSaveShortcut(e) { + if (e.isDefaultPrevented()) return false; + if (!e.metaKey && !e.ctrlKey) return false; + if (e.key != 'S' && e.key != 's') return false; + + e.preventDefault(); + + // Share and save + share(function(url) { + window.location.href = url + '.go?download=true'; + }); + + return true; + } + + function keyHandler(e) { + if (opts.enableShortcuts && handleSaveShortcut(e)) return; + + if (e.keyCode == 9 && !e.ctrlKey) { + // tab (but not ctrl-tab) + insertTabs(1); + e.preventDefault(); + return false; + } + if (e.keyCode == 13) { + // enter + if (e.shiftKey) { + // +shift + run(); + e.preventDefault(); + return false; + } + if (e.ctrlKey) { + // +control + fmt(); + e.preventDefault(); + } else { + autoindent(e.target); + } + } + return true; + } + code.unbind('keydown').bind('keydown', keyHandler); + var outdiv = $(opts.outputEl).empty(); + var output = $('
    ').appendTo(outdiv);
    +
    +    function body() {
    +      return $(opts.codeEl).val();
    +    }
    +    function setBody(text) {
    +      $(opts.codeEl).val(text);
    +    }
    +    function origin(href) {
    +      return ('' + href)
    +        .split('/')
    +        .slice(0, 3)
    +        .join('/');
    +    }
    +
    +    var pushedEmpty = window.location.pathname == '/';
    +    function inputChanged() {
    +      if (pushedEmpty) {
    +        return;
    +      }
    +      pushedEmpty = true;
    +      $(opts.shareURLEl).hide();
    +      window.history.pushState(null, '', '/');
    +    }
    +    function popState(e) {
    +      if (e === null) {
    +        return;
    +      }
    +      if (e && e.state && e.state.code) {
    +        setBody(e.state.code);
    +      }
    +    }
    +    var rewriteHistory = false;
    +    if (
    +      window.history &&
    +      window.history.pushState &&
    +      window.addEventListener &&
    +      opts.enableHistory
    +    ) {
    +      rewriteHistory = true;
    +      code[0].addEventListener('input', inputChanged);
    +      window.addEventListener('popstate', popState);
    +    }
    +
    +    function setError(error) {
    +      if (running) running.Kill();
    +      lineClear();
    +      lineHighlight(error);
    +      output
    +        .empty()
    +        .addClass('error')
    +        .text(error);
    +    }
    +    function loading() {
    +      lineClear();
    +      if (running) running.Kill();
    +      output.removeClass('error').text('Waiting for remote server...');
    +    }
    +    function run() {
    +      loading();
    +      running = transport.Run(
    +        body(),
    +        highlightOutput(PlaygroundOutput(output[0]))
    +      );
    +    }
    +
    +    function fmt() {
    +      loading();
    +      var data = { body: body() };
    +      if ($(opts.fmtImportEl).is(':checked')) {
    +        data['imports'] = 'true';
    +      }
    +      $.ajax('/fmt', {
    +        data: data,
    +        type: 'POST',
    +        dataType: 'json',
    +        success: function(data) {
    +          if (data.Error) {
    +            setError(data.Error);
    +          } else {
    +            setBody(data.Body);
    +            setError('');
    +          }
    +        },
    +      });
    +    }
    +
    +    var shareURL; // jQuery element to show the shared URL.
    +    var sharing = false; // true if there is a pending request.
    +    var shareCallbacks = [];
    +    function share(opt_callback) {
    +      if (opt_callback) shareCallbacks.push(opt_callback);
    +
    +      if (sharing) return;
    +      sharing = true;
    +
    +      var sharingData = body();
    +      $.ajax('/share', {
    +        processData: false,
    +        data: sharingData,
    +        type: 'POST',
    +        contentType: 'text/plain; charset=utf-8',
    +        complete: function(xhr) {
    +          sharing = false;
    +          if (xhr.status != 200) {
    +            alert('Server error; try again.');
    +            return;
    +          }
    +          if (opts.shareRedirect) {
    +            window.location = opts.shareRedirect + xhr.responseText;
    +          }
    +          var path = '/p/' + xhr.responseText;
    +          var url = origin(window.location) + path;
    +
    +          for (var i = 0; i < shareCallbacks.length; i++) {
    +            shareCallbacks[i](url);
    +          }
    +          shareCallbacks = [];
    +
    +          if (shareURL) {
    +            shareURL
    +              .show()
    +              .val(url)
    +              .focus()
    +              .select();
    +
    +            if (rewriteHistory) {
    +              var historyData = { code: sharingData };
    +              window.history.pushState(historyData, '', path);
    +              pushedEmpty = false;
    +            }
    +          }
    +        },
    +      });
    +    }
    +
    +    $(opts.runEl).click(run);
    +    $(opts.fmtEl).click(fmt);
    +
    +    if (
    +      opts.shareEl !== null &&
    +      (opts.shareURLEl !== null || opts.shareRedirect !== null)
    +    ) {
    +      if (opts.shareURLEl) {
    +        shareURL = $(opts.shareURLEl).hide();
    +      }
    +      $(opts.shareEl).click(function() {
    +        share();
    +      });
    +    }
    +
    +    if (opts.toysEl !== null) {
    +      $(opts.toysEl).bind('change', function() {
    +        var toy = $(this).val();
    +        $.ajax('/doc/play/' + toy, {
    +          processData: false,
    +          type: 'GET',
    +          complete: function(xhr) {
    +            if (xhr.status != 200) {
    +              alert('Server error; try again.');
    +              return;
    +            }
    +            setBody(xhr.responseText);
    +          },
    +        });
    +      });
    +    }
    +  }
    +
    +  window.playground = playground;
    +})();
    +// Copyright 2012 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +function initPlayground(transport) {
    +  'use strict';
    +
    +  function text(node) {
    +    var s = '';
    +    for (var i = 0; i < node.childNodes.length; i++) {
    +      var n = node.childNodes[i];
    +      if (n.nodeType === 1) {
    +        if (n.tagName === 'BUTTON') continue;
    +        if (n.tagName === 'SPAN' && n.className === 'number') continue;
    +        if (n.tagName === 'DIV' || n.tagName === 'BR' || n.tagName === 'PRE') {
    +          s += '\n';
    +        }
    +        s += text(n);
    +        continue;
    +      }
    +      if (n.nodeType === 3) {
    +        s += n.nodeValue;
    +      }
    +    }
    +    return s.replace('\xA0', ' '); // replace non-breaking spaces
    +  }
    +
    +  // When presenter notes are enabled, the index passed
    +  // here will identify the playground to be synced
    +  function init(code, index) {
    +    var output = document.createElement('div');
    +    var outpre = document.createElement('pre');
    +    var running;
    +
    +    if ($ && $(output).resizable) {
    +      $(output).resizable({
    +        handles: 'n,w,nw',
    +        minHeight: 27,
    +        minWidth: 135,
    +        maxHeight: 608,
    +        maxWidth: 990,
    +      });
    +    }
    +
    +    function onKill() {
    +      if (running) running.Kill();
    +      if (window.notesEnabled) updatePlayStorage('onKill', index);
    +    }
    +
    +    function onRun(e) {
    +      var sk = e.shiftKey || localStorage.getItem('play-shiftKey') === 'true';
    +      if (running) running.Kill();
    +      output.style.display = 'block';
    +      outpre.textContent = '';
    +      run1.style.display = 'none';
    +      var options = { Race: sk };
    +      running = transport.Run(text(code), PlaygroundOutput(outpre), options);
    +      if (window.notesEnabled) updatePlayStorage('onRun', index, e);
    +    }
    +
    +    function onClose() {
    +      if (running) running.Kill();
    +      output.style.display = 'none';
    +      run1.style.display = 'inline-block';
    +      if (window.notesEnabled) updatePlayStorage('onClose', index);
    +    }
    +
    +    if (window.notesEnabled) {
    +      playgroundHandlers.onRun.push(onRun);
    +      playgroundHandlers.onClose.push(onClose);
    +      playgroundHandlers.onKill.push(onKill);
    +    }
    +
    +    var run1 = document.createElement('button');
    +    run1.textContent = 'Run';
    +    run1.className = 'run';
    +    run1.addEventListener('click', onRun, false);
    +    var run2 = document.createElement('button');
    +    run2.className = 'run';
    +    run2.textContent = 'Run';
    +    run2.addEventListener('click', onRun, false);
    +    var kill = document.createElement('button');
    +    kill.className = 'kill';
    +    kill.textContent = 'Kill';
    +    kill.addEventListener('click', onKill, false);
    +    var close = document.createElement('button');
    +    close.className = 'close';
    +    close.textContent = 'Close';
    +    close.addEventListener('click', onClose, false);
    +
    +    var button = document.createElement('div');
    +    button.classList.add('buttons');
    +    button.appendChild(run1);
    +    // Hack to simulate insertAfter
    +    code.parentNode.insertBefore(button, code.nextSibling);
    +
    +    var buttons = document.createElement('div');
    +    buttons.classList.add('buttons');
    +    buttons.appendChild(run2);
    +    buttons.appendChild(kill);
    +    buttons.appendChild(close);
    +
    +    output.classList.add('output');
    +    output.appendChild(buttons);
    +    output.appendChild(outpre);
    +    output.style.display = 'none';
    +    code.parentNode.insertBefore(output, button.nextSibling);
    +  }
    +
    +  var play = document.querySelectorAll('div.playground');
    +  for (var i = 0; i < play.length; i++) {
    +    init(play[i], i);
    +  }
    +}
    +
    +initPlayground(new SocketTransport());
    diff --git a/2021/12/02/amex/go_machine_guides_files/slides.js b/2021/12/02/amex/go_machine_guides_files/slides.js
    new file mode 100644
    index 0000000..7c1229e
    --- /dev/null
    +++ b/2021/12/02/amex/go_machine_guides_files/slides.js
    @@ -0,0 +1,635 @@
    +// Copyright 2012 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +var PERMANENT_URL_PREFIX = '/static/';
    +
    +var SLIDE_CLASSES = ['far-past', 'past', 'current', 'next', 'far-next'];
    +
    +var PM_TOUCH_SENSITIVITY = 15;
    +
    +var curSlide;
    +
    +/* ---------------------------------------------------------------------- */
    +/* classList polyfill by Eli Grey
    + * (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */
    +
    +if (
    +  typeof document !== 'undefined' &&
    +  !('classList' in document.createElement('a'))
    +) {
    +  (function(view) {
    +    var classListProp = 'classList',
    +      protoProp = 'prototype',
    +      elemCtrProto = (view.HTMLElement || view.Element)[protoProp],
    +      objCtr = Object;
    +    (strTrim =
    +      String[protoProp].trim ||
    +      function() {
    +        return this.replace(/^\s+|\s+$/g, '');
    +      }),
    +      (arrIndexOf =
    +        Array[protoProp].indexOf ||
    +        function(item) {
    +          for (var i = 0, len = this.length; i < len; i++) {
    +            if (i in this && this[i] === item) {
    +              return i;
    +            }
    +          }
    +          return -1;
    +        }),
    +      // Vendors: please allow content code to instantiate DOMExceptions
    +      (DOMEx = function(type, message) {
    +        this.name = type;
    +        this.code = DOMException[type];
    +        this.message = message;
    +      }),
    +      (checkTokenAndGetIndex = function(classList, token) {
    +        if (token === '') {
    +          throw new DOMEx(
    +            'SYNTAX_ERR',
    +            'An invalid or illegal string was specified'
    +          );
    +        }
    +        if (/\s/.test(token)) {
    +          throw new DOMEx(
    +            'INVALID_CHARACTER_ERR',
    +            'String contains an invalid character'
    +          );
    +        }
    +        return arrIndexOf.call(classList, token);
    +      }),
    +      (ClassList = function(elem) {
    +        var trimmedClasses = strTrim.call(elem.className),
    +          classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [];
    +        for (var i = 0, len = classes.length; i < len; i++) {
    +          this.push(classes[i]);
    +        }
    +        this._updateClassName = function() {
    +          elem.className = this.toString();
    +        };
    +      }),
    +      (classListProto = ClassList[protoProp] = []),
    +      (classListGetter = function() {
    +        return new ClassList(this);
    +      });
    +    // Most DOMException implementations don't allow calling DOMException's toString()
    +    // on non-DOMExceptions. Error's toString() is sufficient here.
    +    DOMEx[protoProp] = Error[protoProp];
    +    classListProto.item = function(i) {
    +      return this[i] || null;
    +    };
    +    classListProto.contains = function(token) {
    +      token += '';
    +      return checkTokenAndGetIndex(this, token) !== -1;
    +    };
    +    classListProto.add = function(token) {
    +      token += '';
    +      if (checkTokenAndGetIndex(this, token) === -1) {
    +        this.push(token);
    +        this._updateClassName();
    +      }
    +    };
    +    classListProto.remove = function(token) {
    +      token += '';
    +      var index = checkTokenAndGetIndex(this, token);
    +      if (index !== -1) {
    +        this.splice(index, 1);
    +        this._updateClassName();
    +      }
    +    };
    +    classListProto.toggle = function(token) {
    +      token += '';
    +      if (checkTokenAndGetIndex(this, token) === -1) {
    +        this.add(token);
    +      } else {
    +        this.remove(token);
    +      }
    +    };
    +    classListProto.toString = function() {
    +      return this.join(' ');
    +    };
    +
    +    if (objCtr.defineProperty) {
    +      var classListPropDesc = {
    +        get: classListGetter,
    +        enumerable: true,
    +        configurable: true,
    +      };
    +      try {
    +        objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
    +      } catch (ex) {
    +        // IE 8 doesn't support enumerable:true
    +        if (ex.number === -0x7ff5ec54) {
    +          classListPropDesc.enumerable = false;
    +          objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
    +        }
    +      }
    +    } else if (objCtr[protoProp].__defineGetter__) {
    +      elemCtrProto.__defineGetter__(classListProp, classListGetter);
    +    }
    +  })(self);
    +}
    +/* ---------------------------------------------------------------------- */
    +
    +/* Slide movement */
    +
    +function hideHelpText() {
    +  document.getElementById('help').style.display = 'none';
    +}
    +
    +function getSlideEl(no) {
    +  if (no < 0 || no >= slideEls.length) {
    +    return null;
    +  } else {
    +    return slideEls[no];
    +  }
    +}
    +
    +function updateSlideClass(slideNo, className) {
    +  var el = getSlideEl(slideNo);
    +
    +  if (!el) {
    +    return;
    +  }
    +
    +  if (className) {
    +    el.classList.add(className);
    +  }
    +
    +  for (var i in SLIDE_CLASSES) {
    +    if (className != SLIDE_CLASSES[i]) {
    +      el.classList.remove(SLIDE_CLASSES[i]);
    +    }
    +  }
    +}
    +
    +function updateSlides() {
    +  if (window.trackPageview) window.trackPageview();
    +
    +  for (var i = 0; i < slideEls.length; i++) {
    +    switch (i) {
    +      case curSlide - 2:
    +        updateSlideClass(i, 'far-past');
    +        break;
    +      case curSlide - 1:
    +        updateSlideClass(i, 'past');
    +        break;
    +      case curSlide:
    +        updateSlideClass(i, 'current');
    +        break;
    +      case curSlide + 1:
    +        updateSlideClass(i, 'next');
    +        break;
    +      case curSlide + 2:
    +        updateSlideClass(i, 'far-next');
    +        break;
    +      default:
    +        updateSlideClass(i);
    +        break;
    +    }
    +  }
    +
    +  triggerLeaveEvent(curSlide - 1);
    +  triggerEnterEvent(curSlide);
    +
    +  window.setTimeout(function() {
    +    // Hide after the slide
    +    disableSlideFrames(curSlide - 2);
    +  }, 301);
    +
    +  enableSlideFrames(curSlide - 1);
    +  enableSlideFrames(curSlide + 2);
    +
    +  updateHash();
    +}
    +
    +function prevSlide() {
    +  hideHelpText();
    +  if (curSlide > 0) {
    +    curSlide--;
    +
    +    updateSlides();
    +  }
    +
    +  if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide);
    +}
    +
    +function nextSlide() {
    +  hideHelpText();
    +  if (curSlide < slideEls.length - 1) {
    +    curSlide++;
    +
    +    updateSlides();
    +  }
    +
    +  if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide);
    +}
    +
    +/* Slide events */
    +
    +function triggerEnterEvent(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var onEnter = el.getAttribute('onslideenter');
    +  if (onEnter) {
    +    new Function(onEnter).call(el);
    +  }
    +
    +  var evt = document.createEvent('Event');
    +  evt.initEvent('slideenter', true, true);
    +  evt.slideNumber = no + 1; // Make it readable
    +
    +  el.dispatchEvent(evt);
    +}
    +
    +function triggerLeaveEvent(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var onLeave = el.getAttribute('onslideleave');
    +  if (onLeave) {
    +    new Function(onLeave).call(el);
    +  }
    +
    +  var evt = document.createEvent('Event');
    +  evt.initEvent('slideleave', true, true);
    +  evt.slideNumber = no + 1; // Make it readable
    +
    +  el.dispatchEvent(evt);
    +}
    +
    +/* Touch events */
    +
    +function handleTouchStart(event) {
    +  if (event.touches.length == 1) {
    +    touchDX = 0;
    +    touchDY = 0;
    +
    +    touchStartX = event.touches[0].pageX;
    +    touchStartY = event.touches[0].pageY;
    +
    +    document.body.addEventListener('touchmove', handleTouchMove, true);
    +    document.body.addEventListener('touchend', handleTouchEnd, true);
    +  }
    +}
    +
    +function handleTouchMove(event) {
    +  if (event.touches.length > 1) {
    +    cancelTouch();
    +  } else {
    +    touchDX = event.touches[0].pageX - touchStartX;
    +    touchDY = event.touches[0].pageY - touchStartY;
    +    event.preventDefault();
    +  }
    +}
    +
    +function handleTouchEnd(event) {
    +  var dx = Math.abs(touchDX);
    +  var dy = Math.abs(touchDY);
    +
    +  if (dx > PM_TOUCH_SENSITIVITY && dy < (dx * 2) / 3) {
    +    if (touchDX > 0) {
    +      prevSlide();
    +    } else {
    +      nextSlide();
    +    }
    +  }
    +
    +  cancelTouch();
    +}
    +
    +function cancelTouch() {
    +  document.body.removeEventListener('touchmove', handleTouchMove, true);
    +  document.body.removeEventListener('touchend', handleTouchEnd, true);
    +}
    +
    +/* Preloading frames */
    +
    +function disableSlideFrames(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var frames = el.getElementsByTagName('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    disableFrame(frame);
    +  }
    +}
    +
    +function enableSlideFrames(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var frames = el.getElementsByTagName('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    enableFrame(frame);
    +  }
    +}
    +
    +function disableFrame(frame) {
    +  frame.src = 'about:blank';
    +}
    +
    +function enableFrame(frame) {
    +  var src = frame._src;
    +
    +  if (frame.src != src && src != 'about:blank') {
    +    frame.src = src;
    +  }
    +}
    +
    +function setupFrames() {
    +  var frames = document.querySelectorAll('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    frame._src = frame.src;
    +    disableFrame(frame);
    +  }
    +
    +  enableSlideFrames(curSlide);
    +  enableSlideFrames(curSlide + 1);
    +  enableSlideFrames(curSlide + 2);
    +}
    +
    +function setupInteraction() {
    +  /* Clicking and tapping */
    +
    +  var el = document.createElement('div');
    +  el.className = 'slide-area';
    +  el.id = 'prev-slide-area';
    +  el.addEventListener('click', prevSlide, false);
    +  document.querySelector('section.slides').appendChild(el);
    +
    +  var el = document.createElement('div');
    +  el.className = 'slide-area';
    +  el.id = 'next-slide-area';
    +  el.addEventListener('click', nextSlide, false);
    +  document.querySelector('section.slides').appendChild(el);
    +
    +  /* Swiping */
    +
    +  document.body.addEventListener('touchstart', handleTouchStart, false);
    +}
    +
    +/* Hash functions */
    +
    +function getCurSlideFromHash() {
    +  var slideNo = parseInt(location.hash.substr(1));
    +
    +  if (slideNo) {
    +    curSlide = slideNo - 1;
    +  } else {
    +    curSlide = 0;
    +  }
    +}
    +
    +function updateHash() {
    +  location.replace('#' + (curSlide + 1));
    +}
    +
    +/* Event listeners */
    +
    +function handleBodyKeyDown(event) {
    +  // If we're in a code element, only handle pgup/down.
    +  var inCode = event.target.classList.contains('code');
    +
    +  switch (event.keyCode) {
    +    case 78: // 'N' opens presenter notes window
    +      if (!inCode && notesEnabled) toggleNotesWindow();
    +      break;
    +    case 72: // 'H' hides the help text
    +    case 27: // escape key
    +      if (!inCode) hideHelpText();
    +      break;
    +
    +    case 39: // right arrow
    +    case 13: // Enter
    +    case 32: // space
    +      if (inCode) break;
    +    case 34: // PgDn
    +      nextSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 37: // left arrow
    +    case 8: // Backspace
    +      if (inCode) break;
    +    case 33: // PgUp
    +      prevSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 40: // down arrow
    +      if (inCode) break;
    +      nextSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 38: // up arrow
    +      if (inCode) break;
    +      prevSlide();
    +      event.preventDefault();
    +      break;
    +  }
    +}
    +
    +function scaleSmallViewports() {
    +  var el = document.querySelector('section.slides');
    +  var transform = '';
    +  var sWidthPx = 1250;
    +  var sHeightPx = 750;
    +  var sAspectRatio = sWidthPx / sHeightPx;
    +  var wAspectRatio = window.innerWidth / window.innerHeight;
    +
    +  if (wAspectRatio <= sAspectRatio && window.innerWidth < sWidthPx) {
    +    transform = 'scale(' + window.innerWidth / sWidthPx + ')';
    +  } else if (window.innerHeight < sHeightPx) {
    +    transform = 'scale(' + window.innerHeight / sHeightPx + ')';
    +  }
    +  el.style.transform = transform;
    +}
    +
    +function addEventListeners() {
    +  document.addEventListener('keydown', handleBodyKeyDown, false);
    +  var resizeTimeout;
    +  window.addEventListener('resize', function() {
    +    // throttle resize events
    +    window.clearTimeout(resizeTimeout);
    +    resizeTimeout = window.setTimeout(function() {
    +      resizeTimeout = null;
    +      scaleSmallViewports();
    +    }, 50);
    +  });
    +
    +  // Force reset transform property of section.slides when printing page.
    +  // Use both onbeforeprint and matchMedia for compatibility with different browsers.
    +  var beforePrint = function() {
    +    var el = document.querySelector('section.slides');
    +    el.style.transform = '';
    +  };
    +  window.onbeforeprint = beforePrint;
    +  if (window.matchMedia) {
    +    var mediaQueryList = window.matchMedia('print');
    +    mediaQueryList.addListener(function(mql) {
    +      if (mql.matches) beforePrint();
    +    });
    +  }
    +}
    +
    +/* Initialization */
    +
    +function addFontStyle() {
    +  var el = document.createElement('link');
    +  el.rel = 'stylesheet';
    +  el.type = 'text/css';
    +  el.href =
    +    '//fonts.googleapis.com/css?family=' +
    +    'Open+Sans:regular,semibold,italic,italicsemibold|Droid+Sans+Mono';
    +
    +  document.body.appendChild(el);
    +}
    +
    +function addGeneralStyle() {
    +  var el = document.createElement('link');
    +  el.rel = 'stylesheet';
    +  el.type = 'text/css';
    +  el.href = PERMANENT_URL_PREFIX + 'styles.css';
    +  document.body.appendChild(el);
    +
    +  var el = document.createElement('meta');
    +  el.name = 'viewport';
    +  el.content = 'width=device-width,height=device-height,initial-scale=1';
    +  document.querySelector('head').appendChild(el);
    +
    +  var el = document.createElement('meta');
    +  el.name = 'apple-mobile-web-app-capable';
    +  el.content = 'yes';
    +  document.querySelector('head').appendChild(el);
    +
    +  scaleSmallViewports();
    +}
    +
    +function handleDomLoaded() {
    +  slideEls = document.querySelectorAll('section.slides > article');
    +
    +  setupFrames();
    +
    +  addFontStyle();
    +  addGeneralStyle();
    +  addEventListeners();
    +
    +  updateSlides();
    +
    +  setupInteraction();
    +
    +  if (
    +    window.location.hostname == 'localhost' ||
    +    window.location.hostname == '127.0.0.1' ||
    +    window.location.hostname == '::1'
    +  ) {
    +    hideHelpText();
    +  }
    +
    +  document.body.classList.add('loaded');
    +
    +  setupNotesSync();
    +}
    +
    +function initialize() {
    +  getCurSlideFromHash();
    +
    +  if (window['_DEBUG']) {
    +    PERMANENT_URL_PREFIX = '../';
    +  }
    +
    +  if (window['_DCL']) {
    +    handleDomLoaded();
    +  } else {
    +    document.addEventListener('DOMContentLoaded', handleDomLoaded, false);
    +  }
    +}
    +
    +// If ?debug exists then load the script relative instead of absolute
    +if (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) {
    +  document.addEventListener(
    +    'DOMContentLoaded',
    +    function() {
    +      // Avoid missing the DomContentLoaded event
    +      window['_DCL'] = true;
    +    },
    +    false
    +  );
    +
    +  window['_DEBUG'] = true;
    +  var script = document.createElement('script');
    +  script.type = 'text/javascript';
    +  script.src = '../slides.js';
    +  var s = document.getElementsByTagName('script')[0];
    +  s.parentNode.insertBefore(script, s);
    +
    +  // Remove this script
    +  s.parentNode.removeChild(s);
    +} else {
    +  initialize();
    +}
    +
    +/* Synchronize windows when notes are enabled */
    +
    +function setupNotesSync() {
    +  if (!notesEnabled) return;
    +
    +  function setupPlayResizeSync() {
    +    var out = document.getElementsByClassName('output');
    +    for (var i = 0; i < out.length; i++) {
    +      $(out[i]).bind('resize', function(event) {
    +        if ($(event.target).hasClass('ui-resizable')) {
    +          localStorage.setItem('play-index', i);
    +          localStorage.setItem('output-style', out[i].style.cssText);
    +        }
    +      });
    +    }
    +  }
    +  function setupPlayCodeSync() {
    +    var play = document.querySelectorAll('div.playground');
    +    for (var i = 0; i < play.length; i++) {
    +      play[i].addEventListener('input', inputHandler, false);
    +
    +      function inputHandler(e) {
    +        localStorage.setItem('play-index', i);
    +        localStorage.setItem('play-code', e.target.innerHTML);
    +      }
    +    }
    +  }
    +
    +  setupPlayCodeSync();
    +  setupPlayResizeSync();
    +  localStorage.setItem(destSlideKey(), curSlide);
    +  window.addEventListener('storage', updateOtherWindow, false);
    +}
    +
    +// An update to local storage is caught only by the other window
    +// The triggering window does not handle any sync actions
    +function updateOtherWindow(e) {
    +  // Ignore remove storage events which are not meant to update the other window
    +  var isRemoveStorageEvent = !e.newValue;
    +  if (isRemoveStorageEvent) return;
    +
    +  var destSlide = localStorage.getItem(destSlideKey());
    +  while (destSlide > curSlide) {
    +    nextSlide();
    +  }
    +  while (destSlide < curSlide) {
    +    prevSlide();
    +  }
    +
    +  updatePlay(e);
    +  updateNotes();
    +}
    diff --git a/2021/12/02/amex/go_machine_guides_files/styles.css b/2021/12/02/amex/go_machine_guides_files/styles.css
    new file mode 100644
    index 0000000..5edfde9
    --- /dev/null
    +++ b/2021/12/02/amex/go_machine_guides_files/styles.css
    @@ -0,0 +1,553 @@
    +@media screen {
    +  /* Framework */
    +  html {
    +    height: 100%;
    +  }
    +
    +  body {
    +    margin: 0;
    +    padding: 0;
    +
    +    display: block !important;
    +
    +    height: 100%;
    +    height: 100vh;
    +
    +    overflow: hidden;
    +
    +    background: rgb(215, 215, 215);
    +    background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -webkit-gradient(
    +      radial,
    +      50% 50%,
    +      0,
    +      50% 50%,
    +      500,
    +      from(rgb(240, 240, 240)),
    +      to(rgb(190, 190, 190))
    +    );
    +
    +    -webkit-font-smoothing: antialiased;
    +  }
    +
    +  .slides {
    +    width: 100%;
    +    height: 100%;
    +    left: 0;
    +    top: 0;
    +
    +    position: absolute;
    +
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +
    +  .slides > article {
    +    display: block;
    +
    +    position: absolute;
    +    overflow: hidden;
    +
    +    width: 900px;
    +    height: 700px;
    +
    +    left: 50%;
    +    top: 50%;
    +
    +    margin-left: -450px;
    +    margin-top: -350px;
    +
    +    padding: 40px 60px;
    +
    +    box-sizing: border-box;
    +    -o-box-sizing: border-box;
    +    -moz-box-sizing: border-box;
    +    -webkit-box-sizing: border-box;
    +
    +    border-radius: 10px;
    +    -o-border-radius: 10px;
    +    -moz-border-radius: 10px;
    +    -webkit-border-radius: 10px;
    +
    +    background-color: white;
    +
    +    border: 1px solid rgba(0, 0, 0, 0.3);
    +
    +    transition: transform 0.3s ease-out;
    +    -o-transition: -o-transform 0.3s ease-out;
    +    -moz-transition: -moz-transform 0.3s ease-out;
    +    -webkit-transition: -webkit-transform 0.3s ease-out;
    +  }
    +  .slides.layout-widescreen > article {
    +    margin-left: -550px;
    +    width: 1100px;
    +  }
    +  .slides.layout-faux-widescreen > article {
    +    margin-left: -550px;
    +    width: 1100px;
    +
    +    padding: 40px 160px;
    +  }
    +
    +  .slides.layout-widescreen > article:not(.nobackground):not(.biglogo),
    +  .slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) {
    +    background-position-x: 0, 840px;
    +  }
    +
    +  /* Clickable/tappable areas */
    +
    +  .slide-area {
    +    z-index: 1000;
    +
    +    position: absolute;
    +    left: 0;
    +    top: 0;
    +    width: 150px;
    +    height: 700px;
    +
    +    left: 50%;
    +    top: 50%;
    +
    +    cursor: pointer;
    +    margin-top: -350px;
    +
    +    tap-highlight-color: transparent;
    +    -o-tap-highlight-color: transparent;
    +    -moz-tap-highlight-color: transparent;
    +    -webkit-tap-highlight-color: transparent;
    +  }
    +  #prev-slide-area {
    +    margin-left: -550px;
    +  }
    +  #next-slide-area {
    +    margin-left: 400px;
    +  }
    +  .slides.layout-widescreen #prev-slide-area,
    +  .slides.layout-faux-widescreen #prev-slide-area {
    +    margin-left: -650px;
    +  }
    +  .slides.layout-widescreen #next-slide-area,
    +  .slides.layout-faux-widescreen #next-slide-area {
    +    margin-left: 500px;
    +  }
    +
    +  /* Slides */
    +
    +  .slides > article {
    +    display: none;
    +  }
    +  .slides > article.far-past {
    +    display: block;
    +    transform: translate(-2040px);
    +    -o-transform: translate(-2040px);
    +    -moz-transform: translate(-2040px);
    +    -webkit-transform: translate3d(-2040px, 0, 0);
    +  }
    +  .slides > article.past {
    +    display: block;
    +    transform: translate(-1020px);
    +    -o-transform: translate(-1020px);
    +    -moz-transform: translate(-1020px);
    +    -webkit-transform: translate3d(-1020px, 0, 0);
    +  }
    +  .slides > article.current {
    +    display: block;
    +    transform: translate(0);
    +    -o-transform: translate(0);
    +    -moz-transform: translate(0);
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +  .slides > article.next {
    +    display: block;
    +    transform: translate(1020px);
    +    -o-transform: translate(1020px);
    +    -moz-transform: translate(1020px);
    +    -webkit-transform: translate3d(1020px, 0, 0);
    +  }
    +  .slides > article.far-next {
    +    display: block;
    +    transform: translate(2040px);
    +    -o-transform: translate(2040px);
    +    -moz-transform: translate(2040px);
    +    -webkit-transform: translate3d(2040px, 0, 0);
    +  }
    +
    +  .slides.layout-widescreen > article.far-past,
    +  .slides.layout-faux-widescreen > article.far-past {
    +    display: block;
    +    transform: translate(-2260px);
    +    -o-transform: translate(-2260px);
    +    -moz-transform: translate(-2260px);
    +    -webkit-transform: translate3d(-2260px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.past,
    +  .slides.layout-faux-widescreen > article.past {
    +    display: block;
    +    transform: translate(-1130px);
    +    -o-transform: translate(-1130px);
    +    -moz-transform: translate(-1130px);
    +    -webkit-transform: translate3d(-1130px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.current,
    +  .slides.layout-faux-widescreen > article.current {
    +    display: block;
    +    transform: translate(0);
    +    -o-transform: translate(0);
    +    -moz-transform: translate(0);
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.next,
    +  .slides.layout-faux-widescreen > article.next {
    +    display: block;
    +    transform: translate(1130px);
    +    -o-transform: translate(1130px);
    +    -moz-transform: translate(1130px);
    +    -webkit-transform: translate3d(1130px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.far-next,
    +  .slides.layout-faux-widescreen > article.far-next {
    +    display: block;
    +    transform: translate(2260px);
    +    -o-transform: translate(2260px);
    +    -moz-transform: translate(2260px);
    +    -webkit-transform: translate3d(2260px, 0, 0);
    +  }
    +}
    +
    +@media print {
    +  /* Set page layout */
    +  @page {
    +    size: A4 landscape;
    +  }
    +
    +  body {
    +    display: block !important;
    +  }
    +
    +  .slides > article {
    +    display: block;
    +
    +    position: relative;
    +
    +    page-break-inside: never;
    +    page-break-after: always;
    +
    +    overflow: hidden;
    +  }
    +
    +  h2 {
    +    position: static !important;
    +    margin-top: 400px !important;
    +    margin-bottom: 100px !important;
    +  }
    +
    +  div.code {
    +    background: rgb(240, 240, 240);
    +  }
    +
    +  /* Add explicit links */
    +  a:link:after,
    +  a:visited:after {
    +    content: ' (' attr(href) ') ';
    +    font-size: 50%;
    +  }
    +
    +  #help {
    +    display: none;
    +    visibility: hidden;
    +  }
    +}
    +
    +/* Styles for slides */
    +
    +.slides > article {
    +  font-family: 'Open Sans', Arial, sans-serif;
    +
    +  color: black;
    +  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
    +
    +  font-size: 26px;
    +  line-height: 36px;
    +
    +  letter-spacing: -1px;
    +}
    +
    +b {
    +  font-weight: 600;
    +}
    +
    +a {
    +  color: rgb(0, 102, 204);
    +  text-decoration: none;
    +}
    +a:visited {
    +  color: rgba(0, 102, 204, 0.75);
    +}
    +a:hover {
    +  color: black;
    +}
    +
    +p {
    +  margin: 0;
    +  padding: 0;
    +
    +  margin-top: 20px;
    +}
    +p:first-child {
    +  margin-top: 0;
    +}
    +
    +h1 {
    +  font-size: 60px;
    +  line-height: 60px;
    +
    +  padding: 0;
    +  margin: 0;
    +  margin-top: 200px;
    +  margin-bottom: 5px;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -3px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +h2 {
    +  font-size: 45px;
    +  line-height: 45px;
    +
    +  position: absolute;
    +  bottom: 150px;
    +
    +  padding: 0;
    +  margin: 0;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -2px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +h3 {
    +  font-size: 30px;
    +  line-height: 36px;
    +
    +  padding: 0;
    +  margin: 0;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -1px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +ul {
    +  margin: 0;
    +  padding: 0;
    +  margin-top: 20px;
    +  margin-left: 1.5em;
    +}
    +li {
    +  padding: 0;
    +  margin: 0 0 0.5em 0;
    +}
    +
    +div.code {
    +  padding: 5px 10px;
    +  margin-top: 20px;
    +  margin-bottom: 20px;
    +  overflow: hidden;
    +
    +  background: rgb(240, 240, 240);
    +  border: 1px solid rgb(224, 224, 224);
    +}
    +pre {
    +  margin: 0;
    +  padding: 0;
    +
    +  font-family: 'Droid Sans Mono', 'Courier New', monospace;
    +  font-size: 18px;
    +  line-height: 24px;
    +  letter-spacing: -1px;
    +
    +  color: black;
    +}
    +
    +pre.numbers span:before {
    +  content: attr(num);
    +  margin-right: 1em;
    +  display: inline-block;
    +}
    +
    +code {
    +  font-size: 95%;
    +  font-family: 'Droid Sans Mono', 'Courier New', monospace;
    +
    +  color: black;
    +}
    +
    +article > .image,
    +article > .video {
    +  text-align: center;
    +  margin-top: 40px;
    +}
    +
    +article.background {
    +  background-size: contain;
    +  background-repeat: round;
    +}
    +
    +table {
    +  width: 100%;
    +  border-collapse: collapse;
    +  margin-top: 40px;
    +}
    +th {
    +  font-weight: 600;
    +  text-align: left;
    +}
    +td,
    +th {
    +  border: 1px solid rgb(224, 224, 224);
    +  padding: 5px 10px;
    +  vertical-align: top;
    +}
    +
    +p.link {
    +  margin-left: 20px;
    +}
    +
    +.pagenumber {
    +  color: #8c8c8c;
    +  font-size: 75%;
    +  position: absolute;
    +  bottom: 0px;
    +  right: 10px;
    +}
    +
    +/* Code */
    +div.code {
    +  outline: 0px solid transparent;
    +}
    +div.playground {
    +  position: relative;
    +}
    +div.output {
    +  position: absolute;
    +  left: 50%;
    +  top: 50%;
    +  right: 40px;
    +  bottom: 40px;
    +  background: #202020;
    +  padding: 5px 10px;
    +  z-index: 2;
    +
    +  border-radius: 10px;
    +  -o-border-radius: 10px;
    +  -moz-border-radius: 10px;
    +  -webkit-border-radius: 10px;
    +}
    +div.output pre {
    +  margin: 0;
    +  padding: 0;
    +  background: none;
    +  border: none;
    +  width: 100%;
    +  height: 100%;
    +  overflow: auto;
    +}
    +div.output .stdout,
    +div.output pre {
    +  color: #e6e6e6;
    +}
    +div.output .stderr,
    +div.output .error {
    +  color: rgb(255, 200, 200);
    +}
    +div.output .system,
    +div.output .exit {
    +  color: rgb(255, 230, 120);
    +}
    +.buttons {
    +  position: relative;
    +  float: right;
    +  top: -60px;
    +  right: 10px;
    +}
    +div.output .buttons {
    +  position: absolute;
    +  float: none;
    +  top: auto;
    +  right: 5px;
    +  bottom: 5px;
    +}
    +
    +/* Presenter details */
    +.presenter {
    +  margin-top: 20px;
    +}
    +.presenter p,
    +.presenter .link {
    +  margin: 0;
    +  font-size: 28px;
    +  line-height: 1.2em;
    +}
    +
    +/* Output resize details */
    +.ui-resizable-handle {
    +  position: absolute;
    +}
    +.ui-resizable-n {
    +  cursor: n-resize;
    +  height: 7px;
    +  width: 100%;
    +  top: -5px;
    +  left: 0;
    +}
    +.ui-resizable-w {
    +  cursor: w-resize;
    +  width: 7px;
    +  left: -5px;
    +  top: 0;
    +  height: 100%;
    +}
    +.ui-resizable-nw {
    +  cursor: nw-resize;
    +  width: 9px;
    +  height: 9px;
    +  left: -5px;
    +  top: -5px;
    +}
    +iframe {
    +  border: none;
    +}
    +figcaption {
    +  color: #666;
    +  text-align: center;
    +  font-size: 0.75em;
    +}
    +
    +#help {
    +  font-family: 'Open Sans', Arial, sans-serif;
    +  text-align: center;
    +  color: white;
    +  background: #000;
    +  opacity: 0.5;
    +  position: fixed;
    +  bottom: 25px;
    +  left: 50px;
    +  right: 50px;
    +  padding: 20px;
    +
    +  border-radius: 10px;
    +  -o-border-radius: 10px;
    +  -moz-border-radius: 10px;
    +  -webkit-border-radius: 10px;
    +}
    diff --git a/2021/12/02/amex/go_machine_guides_files/trace_ncpu+nthreads.png b/2021/12/02/amex/go_machine_guides_files/trace_ncpu+nthreads.png
    new file mode 100644
    index 0000000..e3785e3
    Binary files /dev/null and b/2021/12/02/amex/go_machine_guides_files/trace_ncpu+nthreads.png differ
    diff --git a/2021/12/02/amex/go_machine_guides_files/unsafe-simplemli.png b/2021/12/02/amex/go_machine_guides_files/unsafe-simplemli.png
    new file mode 100644
    index 0000000..9a86b18
    Binary files /dev/null and b/2021/12/02/amex/go_machine_guides_files/unsafe-simplemli.png differ
    diff --git a/2021/12/02/amex/go_machine_guides_files/xbank-improvement.png b/2021/12/02/amex/go_machine_guides_files/xbank-improvement.png
    new file mode 100644
    index 0000000..4d2fc55
    Binary files /dev/null and b/2021/12/02/amex/go_machine_guides_files/xbank-improvement.png differ
    diff --git a/2021/12/02/amex/gomachine.slide b/2021/12/02/amex/gomachine.slide
    new file mode 100644
    index 0000000..4a13185
    --- /dev/null
    +++ b/2021/12/02/amex/gomachine.slide
    @@ -0,0 +1,254 @@
    +# Go, as the machine guides
    +Tags: go, high-performance
    +
    +Emmanuel T Odeke
    +Orijtech, Inc.
    +Thu 2 Dec 2021
    +emmanuel@orijtech.com
    +https://go.orijtech.com
    +@odeke_et
    +
    +## Go, as the machine guides
    +
    +## Let the machine guide you
    +- "Genius of Alexander, Marie Louise Elisabeth Vigée-Lebrun, 1814"
    +
    + +## About this talk +- Dissecting some common scenarios +- Empowering you with productivity and dexterity with the Go programming language +- High performance engineering tools and tips +- Digging deeper than the surface shows +- Pragmatic problem solving +- Real world experiences and examples +- Let the machine guide you! + +## About myself +- Emmanuel T Odeke +- Building [Orijtech, Inc](https://orijtech.com/) +- Enjoy learning and solving problems; I am mostly self taught +- Always learning +- Avid open source producer and consumer +- Core contributor and leader on the [Go programming language](https://golang.org/) +- Core contributor and leader on [OpenCensus](https://opencensus.io/) and [OpenTelemetry](https://opentelemetry.io/) +- Always learning, and enjoy solving problems! +- Building critical and high performance software engineering tools like Go, static analyzers, CI/CD infrastructure, databases, observability infrastructure, security infrastructure + +## About Go +- The Go programming language is the undisputed language of the cloud +- 30+% of the Fortune 100 use Go, including American Express +- Modern, simple, maintainable, very fast, robust, performant, easy to learn and teach +- Highly productive language +- Been public for 12 years since (November 8th 2009) after release from Google +- Very smart people who deeply care about developer productivity & efficiency +- Mature language collaboratively contributed to by the community +- It has hidden gems that we should all wield + +## Go as the machine guides +- What's odd about this code? You encounter it in a code review + +.play sanitize_balances.go + +- You could say perhaps `sdk.AccAddressFromBech32` returns an error that's ignored? + +## How do we know? + +## How do we know? +- We build upon layers of unknowns and code we can't all examine +- We can't fix what we can't measure nor perceive +- Guess work can't cut it to find needles in haystacks +- The entropy/number of chaotic states is indefinite so we need a way to get to answers really fast + +## Responses +- Context matters +- Should it be of concern? +- If the code is in a hot loop, it matters +- If it isn't significantly called, it doesn't matter +- How can we figure out if it slow? How could we examine and fix these problems? +- How important is it? +- CPU and RAM profiling...[pprof](https://go.dev/blog/pprof/) to the rescue +- We should use it to non-invasively examine the states of our programs... + +## CPU and RAM Profiling +- Modern CPUs have frequencies of >2.1Ghz frequency -- they run 2.1 billion times a second +- Sampling profiling stops the CPU 100 times a second and inquires about the program counter plus state of the heap +- Guiding light that'll show you where you've expended resources +- No need to guess what is going on +- pprof was designed and built in C++, at Google in about 2001 by the esteemed Sanjay Ghemawat + +## Back to that seemingly innocent code... +- What if I told you that this code caused issues for a $150+B market cap ecosystem? + +.play sanitize_balances.go + +## Profile of the code in context +
    + +## What was up with that code? +- The number of accounts was large e.g. 100,000+ accounts +- Invoked sort.Slice (Quicksort in Go) which is a O(n^2) algorithm +- Performed heavy work in a loop and discarded address parsing +- Also some unnecessary work and unnecessary byteslice->string comparisons when looking up maps +- The compound effect was super slow code that had a toll on launches for these folks +- Oops + +## Remedy +- After exorcising the problem, it showed that we needed to only parse addresses once, then use the already memoized values +- Applying map zero byteslice->string conversion in a map look up radically reduced expenses in every dimension by more than 90% +- CPU time reduced by -92.46% +- Allocation counts per operation reduced by -93.76% +- Allocated bytes per operation reduced by -93.76% +- Very happy customers! + +## Exhibit +- Visit [cosmos-sdk/pull#8719](https://github.com/cosmos/cosmos-sdk/pull/8719) and you'll see the radical improvement + +
    + +## The state of your HTTP2 servers in Go + +## Debugging HTTP servers (HTTP/2) +- HTTP/2 is quite popular, https://americanexpress.com uses it! +- Almost all consumer businesses are accessible via a website +- Go has a mature set of libraries for networking [net/*](https://golang.org/pkg/net) and [net/http/*](https://golang.org/pkg/net/http) + +.play enable_http2.go + +## net/http GODEBUG=http2debug=2 +- Prime example was finding an insidious bug in Google Cloud Storage's new storage metadata engine that was written in C++ in June 2019 +- Bug was ["storage: fix TestIntegration_Objects": issue #1482](https://github.com/googleapis/google-cloud-go/issues/1482/) +- We couldn't blame cosmic rays for some of the requests crashing with a 5XX status code and non-uniformly +- I used `GODEBUG=http2debug=2` and sent 10s of thousands of requests then tallied up the failures and discovered oddities +- Passing metadata JSON of `{"contentType": null}` caused the new production C++ backend to crash, it hadn't been properly fuzzed nor tested; a static analyzer could have caught this +- Caused a production freeze at Google for a while + +## Wholistic state of your HTTP and gRPC services? + +## Observability +- Ability to examine the states of your system +- Introspection of programs requires intricate tools and methods +- Tracing and metrics are user defined mechanisms that get added to applications and require context propagation as systems talk to each other +- OpenCensus->OpenTelemetry +- What happens when you can't edit the source? +- Usually there will be instrumented frameworks, but you might need to import code or manually edit code +- Some code requires intricate edits, which at times might not be possible +- Let the machine guide you + +## Go performance tips + +## Continuous benchmarking +- Code changes across small parts of code can build up into something much more +- Without knowing how your change affects general parts of your code, you are flying blind +- Orijtech Inc produced the world's s first continuous benchmarking product, firstly focused on the Go programming language + +## map[string(byteslice)] to retrieve values +- For maps, the keys are required to be immutable and hashable +- When retrieving a value, directly perform the byteslice->string conversion when retrieving the value. The Go compiler +recognizes this pattern as a read-only operation and will perform the reflect.StringHeader retrieval for you + +.play map_key.go + +## map clearing idiom +- Simply use a loop that iterates over keys & invoke `delete(m, key)` + +.play map_clearing_idiom.go + +## map clearing idiom benchmark results +- If we visit [bencher/perfclinic/map-clearing-idiom](https://bencher.orijtech.com/perfclinic/mapclearing/) and examine the results +
    + +## Unsafe/reflect +- Importing ["unsafe"](https://golang.org/pkg/unsafe) in your Go programs comes with a banner warning "Packages that import unsafe may be non-portable and are not protected by the Go 1 compatibility guidelines." +- However, if say you have hot code that allocates a byte slice and you need to parse its string value, so it'll never be referenced out of that section +- unsafe.Pointer and reflect.SliceHeader/reflect.StringHeader come in +- Actual case for further speeding up American Express' "simplemli" per [americanexpress/simplemli/pull#4](https://github.com/americanexpress/simplemli/pull/4) +- Reduction results in elimination of allocations in Decode.MLIA4E + +## Byteslice <-> string conversion +.play unsafe_conversions.go + +## Unsafe+Reflect results in americanexpress/simplemli +Available at [americanexpress/simplemli/pull/4](https://github.com/americanexpress/simplemli/pull/4) +
    + +## Unintended byteslice->string conversion penalty with fmt.*printf +- Some times when using fmt.*printf e.g. fmt.Sprintf, if any of the arguments are byteslices we might get tempted to convert it firstly to a string +- string(byteslice) then invoke fmt.Sprintf +- `fmt.Printf("This is my name: %s\n", string(nameInByteSlice))` +- Expensive and unnecessary, please use the format specifier "%s" or "%q" which will handle the conversion to a string smartly +- `fmt.Printf("This is my name: %s\n", nameInByteSlice)` +- What is the impact of this change? +- Lo and behold, benchmarking to the rescue so we don't have to guess +- Please see https://dashboard.bencher.orijtech.com/benchmark/3245b8e4bbbd44a597480319aaa4b9fe + +## Letting fmt.*printf "%s" handle its conversions +
    +
    + +## Letting fmt.*printf "%s" handle its conversions +
    +
    + +## Scalable and more secure software development guided by the machine? + +## Static analyzers +- Before code is run, examine the Abstract Syntax Tree (AST) and by rules, match patterns that are malformed or could cause insidious bugs +- These help catch insidious bugs that could otherwise cause mayhem, runtime issues, crashes etc +- Developer productivity and correctness are facets of high performance engineering +- Just run `go test` or add staticcheck to your pipelines to run static analyzers +- Orijtech Inc contributes static analyzers to the Go programming language and we've also got many more brewing +- structslop, httperroyzer, sigchanyzer, tickeryzer, testinggoroutine, strconvparseuinterroryzer etc... + +## Internal states of the Go runtime? + +## runtime/trace +- [runtime/trace](https://pkg.go.dev/runtime/trace) provides facilities for generating traces to use with the Go trace executioner +- Prime example, in July 2019, the late Michael T Jones reported that [a particular test that checked the number of threads to have os file reads was failing](https://groups.google.com/g/golang-dev/c/NUlf99mA6YM) +- Everyone on the Go development mailing list was puzzled and didn't know what was going on +- While on a long haul flight back to California on August 29th 2019, I started investigating; as soon as I landed, rushed to my office whiteboard and modelled scenarios +- Emailed MTJ and created custom code to collect runtime traces which indeed showed that there was something fishy going on and that a thread was taken for every read +- I showed my findings at [golang.org/issue/32326](https://github.com/golang/go/issues/32326#issuecomment-526285691) + +## Findings +- Serious bug against expectations of the Go runtime scheduler and runtime poller +
    + +- In `runtime/sys_darwing.go`, when making a syscall, there was a typo to use `entersyscallblock()` instead of `entersyscall` +- Cause confirmed & fixed by Minux Ma; bug shipped in Go1.12 and found in Go1.13 + +## Scheduler and Garbage collector states +- You can learn more by visiting the [Go runtime package's docs](https://golang.org/pkg/runtime/) +- You can see what the scheduler is upto by passing `GODEBUG=scheddetail=1,schedtrace=X ./go_binary` where X is a value in milliseconds + +## Examining the generated assembly + +## Go Assembly examination +- To examine generated code if you really want to dive in, please use `-S` when building your Go binaries +- What does our "Hello, World!" produce? +- When we run: go build -o hw.s -gcflags="-S" helloworld.go + +.play helloworld.go + +## Hello world Assembly +
    + +## Toolbox assembly + +## Summing it all up +- With the arsenal of knowledge that we've garnered here, here is our summary +- Add observability to your toolbox -- Jaeger, Zipkin, Prometheus, Expedia's Haystack are great open source alternatives, or a great APM provider +- OpenCensus, OpenTelemetry to track higher level states of the system such as requests going into your application's server, monitoring to alert on traffic spikes +- GODEBUG=http2debug=2 to debug your net/http HTTP/2 services +- pprof and continuous profiling to dig deep into fine grained states of how your program behaves +- runtime/trace and the Chrome trace viewer using `go tool trace file` to introspect the state of the Go scheduler +- Add benchmarks to your code wholistically; adopt continuous benchmarking or visit Orijtech's own Bencher https://bencher.orijtech.com/ +- Use GODEBUG=scheddetail=1,schedtrace=X +- Assembly examination + +## Reference materials +- Russ S Cox [Profiling Go programs](https://go.dev/blog/pprof/) +- Emmanuel T Odeke [FNIHCS, December 3rd 2020](https://orijtech.github.io/talks/2020/12/03/gosystemsconf/gosystemsconf.htm?f=1#1) +- Emmanuel T Odeke [Taming net/http](https://medium.com/orijtech-developers/taming-net-http-b946edfda562) +- Emmanuel T Odeke [OpenCensus for Go gRPC developers](https://medium.com/orijtech-developers/opencensus-for-go-grpc-developers-7f3ee1ac3d6d) +- Emmanuel T Odeke ["Hello, world!" for web servers in Go with OpenCensus](https://medium.com/orijtech-developers/hello-world-for-web-servers-in-go-with-opencensus-29955b3f02c6) +- Emmanuel T Odeke [x/bank/types: algorithmically fix pathologically slow code](https://github.com/cosmos/cosmos-sdk/pull/8719) diff --git a/2021/12/02/amex/helloworld.go b/2021/12/02/amex/helloworld.go new file mode 100644 index 0000000..c4dc125 --- /dev/null +++ b/2021/12/02/amex/helloworld.go @@ -0,0 +1,5 @@ +package main + +func main() { + println("An honor to be at American Express.. Don't live life without it!") +} diff --git a/2021/12/02/amex/hw.s b/2021/12/02/amex/hw.s new file mode 100755 index 0000000..e9d22fb Binary files /dev/null and b/2021/12/02/amex/hw.s differ diff --git a/2021/12/02/amex/map_clearing_idiom.go b/2021/12/02/amex/map_clearing_idiom.go new file mode 100644 index 0000000..aebf00b --- /dev/null +++ b/2021/12/02/amex/map_clearing_idiom.go @@ -0,0 +1,20 @@ +package main + +func clearNonFast(m map[string]int) { + keys := make([]string, 0, len(m)) + for key := range m { + keys = append(keys, key) + } + + // Do something with keys. + // _ = keys + for _, key := range keys { + delete(m, key) + } +} + +func clearFast(m map[string]int) { + for key := range m { + delete(m, key) + } +} diff --git a/2021/12/02/amex/map_key.go b/2021/12/02/amex/map_key.go new file mode 100644 index 0000000..ed7b7a7 --- /dev/null +++ b/2021/12/02/amex/map_key.go @@ -0,0 +1,12 @@ +package main + +func main() { + m := map[string]int{"ten": 10} + ten := []byte("ten") + // Expensive way. + key := string(ten) + println(m[key]) + + // Cheap way. + println(m[string(ten)]) +} diff --git a/2021/12/02/amex/mapsdeletion-verdict-results.png b/2021/12/02/amex/mapsdeletion-verdict-results.png new file mode 100644 index 0000000..93282ff Binary files /dev/null and b/2021/12/02/amex/mapsdeletion-verdict-results.png differ diff --git a/2021/12/02/amex/sanitize_balances.go b/2021/12/02/amex/sanitize_balances.go new file mode 100644 index 0000000..d627a19 --- /dev/null +++ b/2021/12/02/amex/sanitize_balances.go @@ -0,0 +1,14 @@ +// SanitizeGenesisBalances sorts addresses and coin sets. +func SanitizeGenesisBalances(balances []Balance) []Balance { + sort.Slice(balances, func(i, j int) bool { + addr1, _ := sdk.AccAddressFromBech32(balances[i].Address) + addr2, _ := sdk.AccAddressFromBech32(balances[j].Address) + return bytes.Compare(addr1.Bytes(), addr2.Bytes()) < 0 + }) + + for _, balance := range balances { + balance.Coins = balance.Coins.Sort() + } + + return balances +} \ No newline at end of file diff --git a/2021/12/02/amex/trace_ncpu+nthreads.png b/2021/12/02/amex/trace_ncpu+nthreads.png new file mode 100644 index 0000000..e3785e3 Binary files /dev/null and b/2021/12/02/amex/trace_ncpu+nthreads.png differ diff --git a/2021/12/02/amex/unsafe-simplemli.png b/2021/12/02/amex/unsafe-simplemli.png new file mode 100644 index 0000000..9a86b18 Binary files /dev/null and b/2021/12/02/amex/unsafe-simplemli.png differ diff --git a/2021/12/02/amex/unsafe_conversions.go b/2021/12/02/amex/unsafe_conversions.go new file mode 100644 index 0000000..f97dfb1 --- /dev/null +++ b/2021/12/02/amex/unsafe_conversions.go @@ -0,0 +1,24 @@ +package main + +import ( + "fmt" + "reflect" + "unsafe" +) + +func unsafeByteSliceToStr(b []byte) string { + return *(*string)(unsafe.Pointer(&b)) +} + +func unsafeStrToByteSlice(s string) (b []byte) { + hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + hdr.Cap = len(s) + hdr.Len = len(s) + hdr.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data + return b +} + +func main() { + fmt.Printf("%q\n", unsafeByteSliceToStr([]byte("string"))) + fmt.Printf("% x\n", unsafeStrToByteSlice("string")) +} diff --git a/2021/12/02/amex/xbank-improvement.png b/2021/12/02/amex/xbank-improvement.png new file mode 100644 index 0000000..4d2fc55 Binary files /dev/null and b/2021/12/02/amex/xbank-improvement.png differ diff --git a/2022/09/02/taurus/architecture.jpg b/2022/09/02/taurus/architecture.jpg new file mode 100644 index 0000000..003033c Binary files /dev/null and b/2022/09/02/taurus/architecture.jpg differ diff --git a/2022/09/02/taurus/cancellable1.go b/2022/09/02/taurus/cancellable1.go new file mode 100644 index 0000000..cfc8f8b --- /dev/null +++ b/2022/09/02/taurus/cancellable1.go @@ -0,0 +1,46 @@ +package main + +import ( + "context" + "os" + "os/signal" + "time" +) + +func dispatch(ctx context.Context, n int, fn func() error) chan error { + ch := make(chan error, 1) + go func() { + defer close(ch) + for i := 0; i < n; i++ { + if err := ctx.Err(); err != nil { + if err != context.Canceled { ch <- err } + break + } + + if err := fn(); err != nil { ch <- err } + } + }() + return ch +} + +func main() { + ctx, cancel := context.WithCancel(context.Background()) + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, os.Interrupt) + go func() { + defer cancel() + select { + case <-time.After(5 * time.Second): + case <-sigCh: + } + }() + + resCh := dispatch(ctx, 1e7, func() error { + time.Sleep(time.Second) + return nil + }) + if err := <-resCh; err != nil { + panic(err) + } + println("Completed") +} diff --git a/2022/09/02/taurus/cancellable2.go b/2022/09/02/taurus/cancellable2.go new file mode 100644 index 0000000..435ed17 --- /dev/null +++ b/2022/09/02/taurus/cancellable2.go @@ -0,0 +1,21 @@ +func main() { + ctx, cancel := context.WithCancel(context.Background()) + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, os.Interrupt) + go func() { + defer cancel() + select { + case <-time.After(5 * time.Second): + case <-sigCh: + } + }() + + resCh := cancellable(ctx, 1e7, func() error { + time.Sleep(time.Second) + return nil + }) + if err := <-resCh; err != nil { + panic(err) + } + println("Completed") +} diff --git a/2022/09/02/taurus/go_at_scale.htm b/2022/09/02/taurus/go_at_scale.htm new file mode 100644 index 0000000..95b907c --- /dev/null +++ b/2022/09/02/taurus/go_at_scale.htm @@ -0,0 +1,644 @@ + + + + Go, at scale + + + + + + + + + + + +
    + +
    +

    Go, at scale

    + + + +
    + + +

    + Emmanuel T Odeke +

    + + + +

    + Orijtech, Inc. +

    + + + +

    + Fri 2 Sep 2022 +

    + + +
    + +
    + + + +
    + +

    Go, at scale

    + + 2 +
    + + + +
    + +

    About this talk

    +
      +
    • Go, at scale, so you can go to scale!
    • +
    • From this talk, you should have the tools to get web services up & running in production & also able to observe them & improve your services, plus profile & test them
    • +
    • Using Go to enhance and take your productivity to hyperscale development
    • +
    • Scale: elastic growth/grace with the magnitude and intensity of a problem
    • +
    • Scale to mean team & engineering productivity from 0 to infinity
    • +
    • From startups to Fortune 500 companies: Go is a suitable tool to build production services
    • +
    • Wielding the power of Go can happen with the right focus, humility and urge to learn without pollution of ideas from past technologies
    • +
    • Open minds and the need for speed & productivity!
    • +
    • Lessons from running backend services at companies of all sizes: startup to Fortune 10 companies
    • +
    + + + 3 +
    + + + +
    + +

    About myself

    +
      +
    • Emmanuel T Odeke
    • +
    • Building Orijtech, Inc
    • +
    • Enjoy learning and solving problems; I am mostly self taught
    • +
    • Always learning
    • +
    • Avid open source producer and consumer
    • +
    • Core contributor and leader on the Go programming language
    • +
    • Core contributor and leader on OpenCensus and OpenTelemetry
    • +
    • Always learning, and enjoy solving problems!
    • +
    • Building critical and high performance software engineering tools like Go, static analyzers, CI/CD infrastructure, databases, observability infrastructure, security infrastructure
    • +
    + + + 4 +
    + + + +
    + +

    What is Go?

    +
      +
    • Go is a statically typed, statically linked programming language pioneered at Google
    • +
    • Brain child of Robert Griesemer, Rob Pike, Ken Thompson who conceptualized it allegedly while waiting for C++ builds to complete
    • +
    • Go Co-authors also acknowledged as Russ Cox, Ian Lance Taylor
    • +
    • Hashtag is "golang", language is "Go", website "golang.org"
    • +
    • Go is an expressive language built with principles of pragmatism and engineering productivity
    • +
    • Highly concurrent, modern to help utilize all the cores of modern machines
    • +
    • No need to sweat with pthreads directly nor re-inventing own scheduling yet getting it wrong
    • +
    • The undisputed language of the cloud!
    • +
    + + + 5 +
    + + + +
    + +

    Goroutine dispatched

    + +
    +
    package main
    +
    +import "time"
    +
    +func dispatch(n int, fn func() error) chan error {
    +    ch := make(chan error, 1)
    +    go func() {
    +        defer close(ch)
    +        for i := 0; i < n; i++ {
    +            if err := fn(); err != nil { ch <- err }
    +        }
    +    }()
    +    return ch
    +}
    +
    +func main() {
    +    resCh := dispatch(1e7, func() error { time.Sleep(time.Second); return nil })
    +    if err := <-resCh; err != nil {
    +        panic(err)
    +    }
    +    println("Completed")
    +}
    +
    +
    + + + 6 +
    + + + +
    + +

    What's troublesome in that code?

    +
      +
    • Non-determinism in goroutines happens when the goroutine's course cannot be determined by external conditions nor can its termination be guaranteed
    • +
    • ** commentary in conversation in presentation **
    • +
    + + + 7 +
    + + + +
    + +

    Plumb with context

    +
      +
    • Context allows you to check that the context is still alive hence you can carry on work
    • +
    • Useful in situations such as an HTTP request's processing being stopped after a client goes away or when no longer needed
    • +
    • Multiplex on a channel with Go keyword "select"
    • +
    + + + 8 +
    + + + +
    + +

    Plumb with context

    + +
    +
    package main
    +
    +import (
    +    "context"
    +    "os"
    +    "os/signal"
    +    "time"
    +)
    +
    +func dispatch(ctx context.Context, n int, fn func() error) chan error {
    +    ch := make(chan error, 1)
    +    go func() {
    +        defer close(ch)
    +        for i := 0; i < n; i++ {
    +            if err := ctx.Err(); err != nil {
    +                if err != context.Canceled { ch <- err }
    +                break
    +            }
    +
    +            if err := fn(); err != nil { ch <- err }
    +        }
    +    }()
    +    return ch
    +}
    +
    +func main() {
    +    ctx, cancel := context.WithCancel(context.Background())
    +    sigCh := make(chan os.Signal, 1)
    +    signal.Notify(sigCh, os.Interrupt)
    +    go func() {
    +        defer cancel()
    +        select {
    +        case <-time.After(5 * time.Second):
    +        case <-sigCh:
    +        }
    +    }()
    +
    +    resCh := dispatch(ctx, 1e7, func() error {
    +        time.Sleep(time.Second)
    +        return nil
    +    })
    +    if err := <-resCh; err != nil {
    +        panic(err)
    +    }
    +    println("Completed")
    +}
    +
    +
    + + + 9 +
    + + + +
    + +

    Plumb with context: multiplex on channels with "select"

    + +
    +
    func main() {
    +    ctx, cancel := context.WithCancel(context.Background())
    +    sigCh := make(chan os.Signal, 1)
    +    signal.Notify(sigCh, os.Interrupt)
    +    go func() {
    +        defer cancel()
    +        select {
    +        case <-time.After(5 * time.Second):
    +        case <-sigCh:
    +        }
    +    }()
    +
    +    resCh := cancellable(ctx, 1e7, func() error {
    +        time.Sleep(time.Second)
    +        return nil
    +    })
    +    if err := <-resCh; err != nil {
    +        panic(err)
    +    }
    +    println("Completed")
    +}
    +
    +
    + + + 10 +
    + + + +
    + +

    HTTP request hedging

    +
      +
    • A powerful concept used to help with increasing reliability of backend services
    • +
    • Popularized by Google's Jeff Dean in The Tail at scale
    • +
    • If a service keeps failing, try again with N requests and for the first that returns early, cancel all the rest
    • +
    • Trivial concept to implement natively in Go using net/http.NewRequestWithContext
    • +
    • Send out N requests derived from the same context ctx, get the first successful result and then cancel the context after parsing successfully from the working request
    • +
    • Keeps the machines well utilized!
    • +
    • Just by taking in a context.Context as well as multiplexing on a channel for results, you can race HTTP requests!
    • +
    • With first class features in Go, you now have the power to build prolific features!
    • +
    + + + 11 +
    + + + +
    + +

    Supply chain security

    + + 12 +
    + + + +
    + +

    go.mod is a great forensic tool

    +
      +
    • go.mod and go.sum are 2 distinct files generated and used by the Go build system since Go1.15
    • +
    • Not just for decoration, they are an auditable trail of dependencies
    • +
    • Software Bill of Materials (SBOM) integrated first class into the language
    • +
    • Useful in pining dependencies but also in supply chain analysis
    • +
    • Read more about Go Modules at https://go.dev/ref/mod
    • +
    • Kudos to the Go security team for being this thoughtful!
    • +
    + + + 13 +
    + + + +
    + +

    Go networking & Remote Procedure Call (RPC) libraries

    +
      +
    • net/http -- basis for majority of networking libraries and sufficient for most networking purposes
    • +
    • gRPC library google.golang.org/grpc
    • +
    • net/rpc -- deprecated though, please use gRPC
    • +
    • Apache Thrift
    • +
    + + + 14 +
    + + + +
    + +

    Build microservices

    + + 15 +
    + + + +
    + +

    Take advantage of Go's excellent networking to build microservices

    +
      +
    • Monoliths can be useful but they curtail creativity and development speed because teams can't experiment, rigorously test components and isolate failures when trouble occurs
    • +
    • Go has excellent networking libraries
    • +
    • Look at the package net/http
    • +
    • In less than 10 lines, we can make a production worthy server
    • +
    + +
    +
    package main
    +
    +import (
    +    "fmt"
    +    "net/http"
    +    "time"
    +)
    +
    +func main() {
    +    http.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
    +            fmt.Fprintf(rw, "The time now is: %s:🚨😎\n", time.Now())
    +    })
    +    panic(http.ListenAndServe(":8888", nil))
    +}
    +
    +
    + + + 16 +
    + + + +
    + +

    Tack on HTTPS with Let's Encrypt

    +

    In 14 lines, we can use free TLS certificates from the gracious and awesome Let's Encrypt!

    + +
    +
    package main
    +
    +import (
    +    "net/http"
    +
    +    "golang.org/x/crypto/acme/autocert"
    +)
    +
    +func main() {
    +    http.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
    +        w.Write([]byte("Hello, TLS!"))
    +    })
    +    panic(http.Serve(autocert.NewListener("go.orijtech.com/taurus"), nil))
    +}
    +
    +
    + + + 17 +
    + + + +
    + +

    Observability

    +
      +
    • Observability is the ability to examine the internal states of a system by checking on vital/critical representative signals
    • +
    • Think of what happens what you visit the doctor's office: instead of dissecting you just to figure out what's causing your headache, they'll firstly ask diagnosing questions and take tests
    • +
    • Comes from control theory and Linear Algebra in which if an equation is linearly solveable, you understand the system
    • +
    • For backend applications, we look at function and user defined traces, quantifiable metrics such as throughput (requests per second), memory consumed, file descriptors open, logs
    • +
    • Need a reliable data cruncher and techniques to sift through large amounts of data
    • +
    + + + 18 +
    + + + +
    + +

    Sample web app

    + + + 19 +
    + + + +
    + +

    Observability

    + + + 20 +
    + + + + + + + +
    + +

    Observability results

    + + 22 +
    + + + +
    + +

    Testing

    + + 23 +
    + + + +
    + +

    Write packages that are self contained and testable

    +
      +
    • Business logic should be isolated in packages that can be well tested
    • +
    • Use Go's testing and coverage tools: go test, or go test -coverprofile=out.cover && go tool cover -html=out.cover
    • +
    • Can CPU & memory profile them using runtime/pprof in tests too with: go test -cpuprofile=prof.cpu -memprofile=prof.mem and then use go tool pprof prof.cpu for CPU profiling examinations, or go tool pprof prof.mem for memory profiling examinations
    • +
    • Runtime tracing can be performed using the runtime/trace package
    • +
    + + + 24 +
    + + + +
    + +

    Effectively test out your services using finesse of the language

    +
      +
    • You should be able to test out your packages individually and aim for 100% coverage if possible
    • +
    • Even testing out HTTP handlers and servers is possible, please see net/http/httptest
    • +
    • Study up on Taming net/http by Orijtech Inc
    • +
    • First class fuzzing
    • +
    • Incorporate fuzzers and run them continuously, please see ossfuzz
    • +
    + + + 25 +
    + + + +
    + +

    Go security releases

    +
      +
    • Please update your Go releases often, keep in touch with the Go security mailing list at https://groups.google.com/g/golang-announce/
    • +
    • Update often, lots of gems and hardwork from the security team as well as the general Go releases
    • +
    • Most of the time, upgrading to the latest version gets you speed and feature improvements
    • +
    • Figure out a way of pushing out Go releases within your company
    • +
    • Take advantage of continuous integration and deployment (CI/CD) with the latest releases of Go
    • +
    • File bugs for oddities you might encounter!
    • +
    + + + 26 +
    + + + +
    + +

    Go Community

    + + + + 27 +
    + + + +
    + +

    References

    + + + + 28 +
    + + + + + +
    + + + + + + + + + + + \ No newline at end of file diff --git a/2022/09/02/taurus/go_at_scale_files/architecture.jpg b/2022/09/02/taurus/go_at_scale_files/architecture.jpg new file mode 100644 index 0000000..003033c Binary files /dev/null and b/2022/09/02/taurus/go_at_scale_files/architecture.jpg differ diff --git a/2022/09/02/taurus/go_at_scale_files/css b/2022/09/02/taurus/go_at_scale_files/css new file mode 100644 index 0000000..23432fe --- /dev/null +++ b/2022/09/02/taurus/go_at_scale_files/css @@ -0,0 +1,296 @@ +/* latin */ +@font-face { + font-family: 'Droid Sans Mono'; + font-style: normal; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/droidsansmono/v20/6NUO8FuJNQ2MbkrZ5-J8lKFrp7pRef2rUGIW9g.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtE6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWvU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWu06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWt06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuU6FxZCJgg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtE6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWvU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWu06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWt06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuU6FxZCJgg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-mu0SC55I.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-mu0SC55I.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/2022/09/02/taurus/go_at_scale_files/play.js b/2022/09/02/taurus/go_at_scale_files/play.js new file mode 100644 index 0000000..d62d2bf --- /dev/null +++ b/2022/09/02/taurus/go_at_scale_files/play.js @@ -0,0 +1,715 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
    a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
    t
    ",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
    ",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
    ",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

    ",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
    ","
    "]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
    ").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);/*! jQuery UI - v1.10.2 - 2013-03-20 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.resizable.js +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
    ",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("
    ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
    "),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css("left")),n=t(this.helper.css("top")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===n&&(e.left=t.left+(s.width-e.width),e.top=null),"nw"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidthe.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
    "),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=e(this).data("ui-resizable"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e(["Top","Right","Left","Bottom"]).each(function(e,n){s[e]=t(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,"left")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery);// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +In the absence of any formal way to specify interfaces in JavaScript, +here's a skeleton implementation of a playground transport. + + function Transport() { + // Set up any transport state (eg, make a websocket connection). + return { + Run: function(body, output, options) { + // Compile and run the program 'body' with 'options'. + // Call the 'output' callback to display program output. + return { + Kill: function() { + // Kill the running program. + } + }; + } + }; + } + + // The output callback is called multiple times, and each time it is + // passed an object of this form. + var write = { + Kind: 'string', // 'start', 'stdout', 'stderr', 'end' + Body: 'string' // content of write or end status message + } + + // The first call must be of Kind 'start' with no body. + // Subsequent calls may be of Kind 'stdout' or 'stderr' + // and must have a non-null Body string. + // The final call should be of Kind 'end' with an optional + // Body string, signifying a failure ("killed", for example). + + // The output callback must be of this form. + // See PlaygroundOutput (below) for an implementation. + function outputCallback(write) { + } +*/ + +// HTTPTransport is the default transport. +// enableVet enables running vet if a program was compiled and ran successfully. +// If vet returned any errors, display them before the output of a program. +function HTTPTransport(enableVet) { + 'use strict'; + + function playback(output, data) { + // Backwards compatibility: default values do not affect the output. + var events = data.Events || []; + var errors = data.Errors || ''; + var status = data.Status || 0; + var isTest = data.IsTest || false; + var testsFailed = data.TestsFailed || 0; + + var timeout; + output({ Kind: 'start' }); + function next() { + if (!events || events.length === 0) { + if (isTest) { + if (testsFailed > 0) { + output({ + Kind: 'system', + Body: + '\n' + + testsFailed + + ' test' + + (testsFailed > 1 ? 's' : '') + + ' failed.', + }); + } else { + output({ Kind: 'system', Body: '\nAll tests passed.' }); + } + } else { + if (status > 0) { + output({ Kind: 'end', Body: 'status ' + status + '.' }); + } else { + if (errors !== '') { + // errors are displayed only in the case of timeout. + output({ Kind: 'end', Body: errors + '.' }); + } else { + output({ Kind: 'end' }); + } + } + } + return; + } + var e = events.shift(); + if (e.Delay === 0) { + output({ Kind: e.Kind, Body: e.Message }); + next(); + return; + } + timeout = setTimeout(function() { + output({ Kind: e.Kind, Body: e.Message }); + next(); + }, e.Delay / 1000000); + } + next(); + return { + Stop: function() { + clearTimeout(timeout); + }, + }; + } + + function error(output, msg) { + output({ Kind: 'start' }); + output({ Kind: 'stderr', Body: msg }); + output({ Kind: 'end' }); + } + + function buildFailed(output, msg) { + output({ Kind: 'start' }); + output({ Kind: 'stderr', Body: msg }); + output({ Kind: 'system', Body: '\nGo build failed.' }); + } + + var seq = 0; + return { + Run: function(body, output, options) { + seq++; + var cur = seq; + var playing; + $.ajax('/compile', { + type: 'POST', + data: { version: 2, body: body, withVet: enableVet }, + dataType: 'json', + success: function(data) { + if (seq != cur) return; + if (!data) return; + if (playing != null) playing.Stop(); + if (data.Errors) { + if (data.Errors === 'process took too long') { + // Playback the output that was captured before the timeout. + playing = playback(output, data); + } else { + buildFailed(output, data.Errors); + } + return; + } + if (!data.Events) { + data.Events = []; + } + if (data.VetErrors) { + // Inject errors from the vet as the first events in the output. + data.Events.unshift({ + Message: 'Go vet exited.\n\n', + Kind: 'system', + Delay: 0, + }); + data.Events.unshift({ + Message: data.VetErrors, + Kind: 'stderr', + Delay: 0, + }); + } + + if (!enableVet || data.VetOK || data.VetErrors) { + playing = playback(output, data); + return; + } + + // In case the server support doesn't support + // compile+vet in same request signaled by the + // 'withVet' parameter above, also try the old way. + // TODO: remove this when it falls out of use. + // It is 2019-05-13 now. + $.ajax('/vet', { + data: { body: body }, + type: 'POST', + dataType: 'json', + success: function(dataVet) { + if (dataVet.Errors) { + // inject errors from the vet as the first events in the output + data.Events.unshift({ + Message: 'Go vet exited.\n\n', + Kind: 'system', + Delay: 0, + }); + data.Events.unshift({ + Message: dataVet.Errors, + Kind: 'stderr', + Delay: 0, + }); + } + playing = playback(output, data); + }, + error: function() { + playing = playback(output, data); + }, + }); + }, + error: function() { + error(output, 'Error communicating with remote server.'); + }, + }); + return { + Kill: function() { + if (playing != null) playing.Stop(); + output({ Kind: 'end', Body: 'killed' }); + }, + }; + }, + }; +} + +function SocketTransport() { + 'use strict'; + + var id = 0; + var outputs = {}; + var started = {}; + var websocket; + if (window.location.protocol == 'http:') { + websocket = new WebSocket('ws://' + window.location.host + '/socket'); + } else if (window.location.protocol == 'https:') { + websocket = new WebSocket('wss://' + window.location.host + '/socket'); + } + + websocket.onclose = function() { + console.log('websocket connection closed'); + }; + + websocket.onmessage = function(e) { + var m = JSON.parse(e.data); + var output = outputs[m.Id]; + if (output === null) return; + if (!started[m.Id]) { + output({ Kind: 'start' }); + started[m.Id] = true; + } + output({ Kind: m.Kind, Body: m.Body }); + }; + + function send(m) { + websocket.send(JSON.stringify(m)); + } + + return { + Run: function(body, output, options) { + var thisID = id + ''; + id++; + outputs[thisID] = output; + send({ Id: thisID, Kind: 'run', Body: body, Options: options }); + return { + Kill: function() { + send({ Id: thisID, Kind: 'kill' }); + }, + }; + }, + }; +} + +function PlaygroundOutput(el) { + 'use strict'; + + return function(write) { + if (write.Kind == 'start') { + el.innerHTML = ''; + return; + } + + var cl = 'system'; + if (write.Kind == 'stdout' || write.Kind == 'stderr') cl = write.Kind; + + var m = write.Body; + if (write.Kind == 'end') { + m = '\nProgram exited' + (m ? ': ' + m : '.'); + } + + if (m.indexOf('IMAGE:') === 0) { + // TODO(adg): buffer all writes before creating image + var url = 'data:image/png;base64,' + m.substr(6); + var img = document.createElement('img'); + img.src = url; + el.appendChild(img); + return; + } + + // ^L clears the screen. + var s = m.split('\x0c'); + if (s.length > 1) { + el.innerHTML = ''; + m = s.pop(); + } + + m = m.replace(/&/g, '&'); + m = m.replace(//g, '>'); + + var needScroll = el.scrollTop + el.offsetHeight == el.scrollHeight; + + var span = document.createElement('span'); + span.className = cl; + span.innerHTML = m; + el.appendChild(span); + + if (needScroll) el.scrollTop = el.scrollHeight - el.offsetHeight; + }; +} + +(function() { + function lineHighlight(error) { + var regex = /prog.go:([0-9]+)/g; + var r = regex.exec(error); + while (r) { + $('.lines div') + .eq(r[1] - 1) + .addClass('lineerror'); + r = regex.exec(error); + } + } + function highlightOutput(wrappedOutput) { + return function(write) { + if (write.Body) lineHighlight(write.Body); + wrappedOutput(write); + }; + } + function lineClear() { + $('.lineerror').removeClass('lineerror'); + } + + // opts is an object with these keys + // codeEl - code editor element + // outputEl - program output element + // runEl - run button element + // fmtEl - fmt button element (optional) + // fmtImportEl - fmt "imports" checkbox element (optional) + // shareEl - share button element (optional) + // shareURLEl - share URL text input element (optional) + // shareRedirect - base URL to redirect to on share (optional) + // toysEl - toys select element (optional) + // enableHistory - enable using HTML5 history API (optional) + // transport - playground transport to use (default is HTTPTransport) + // enableShortcuts - whether to enable shortcuts (Ctrl+S/Cmd+S to save) (default is false) + // enableVet - enable running vet and displaying its errors + function playground(opts) { + var code = $(opts.codeEl); + var transport = opts['transport'] || new HTTPTransport(opts['enableVet']); + var running; + + // autoindent helpers. + function insertTabs(n) { + // find the selection start and end + var start = code[0].selectionStart; + var end = code[0].selectionEnd; + // split the textarea content into two, and insert n tabs + var v = code[0].value; + var u = v.substr(0, start); + for (var i = 0; i < n; i++) { + u += '\t'; + } + u += v.substr(end); + // set revised content + code[0].value = u; + // reset caret position after inserted tabs + code[0].selectionStart = start + n; + code[0].selectionEnd = start + n; + } + function autoindent(el) { + var curpos = el.selectionStart; + var tabs = 0; + while (curpos > 0) { + curpos--; + if (el.value[curpos] == '\t') { + tabs++; + } else if (tabs > 0 || el.value[curpos] == '\n') { + break; + } + } + setTimeout(function() { + insertTabs(tabs); + }, 1); + } + + // NOTE(cbro): e is a jQuery event, not a DOM event. + function handleSaveShortcut(e) { + if (e.isDefaultPrevented()) return false; + if (!e.metaKey && !e.ctrlKey) return false; + if (e.key != 'S' && e.key != 's') return false; + + e.preventDefault(); + + // Share and save + share(function(url) { + window.location.href = url + '.go?download=true'; + }); + + return true; + } + + function keyHandler(e) { + if (opts.enableShortcuts && handleSaveShortcut(e)) return; + + if (e.keyCode == 9 && !e.ctrlKey) { + // tab (but not ctrl-tab) + insertTabs(1); + e.preventDefault(); + return false; + } + if (e.keyCode == 13) { + // enter + if (e.shiftKey) { + // +shift + run(); + e.preventDefault(); + return false; + } + if (e.ctrlKey) { + // +control + fmt(); + e.preventDefault(); + } else { + autoindent(e.target); + } + } + return true; + } + code.unbind('keydown').bind('keydown', keyHandler); + var outdiv = $(opts.outputEl).empty(); + var output = $('
    ').appendTo(outdiv);
    +
    +    function body() {
    +      return $(opts.codeEl).val();
    +    }
    +    function setBody(text) {
    +      $(opts.codeEl).val(text);
    +    }
    +    function origin(href) {
    +      return ('' + href)
    +        .split('/')
    +        .slice(0, 3)
    +        .join('/');
    +    }
    +
    +    var pushedEmpty = window.location.pathname == '/';
    +    function inputChanged() {
    +      if (pushedEmpty) {
    +        return;
    +      }
    +      pushedEmpty = true;
    +      $(opts.shareURLEl).hide();
    +      window.history.pushState(null, '', '/');
    +    }
    +    function popState(e) {
    +      if (e === null) {
    +        return;
    +      }
    +      if (e && e.state && e.state.code) {
    +        setBody(e.state.code);
    +      }
    +    }
    +    var rewriteHistory = false;
    +    if (
    +      window.history &&
    +      window.history.pushState &&
    +      window.addEventListener &&
    +      opts.enableHistory
    +    ) {
    +      rewriteHistory = true;
    +      code[0].addEventListener('input', inputChanged);
    +      window.addEventListener('popstate', popState);
    +    }
    +
    +    function setError(error) {
    +      if (running) running.Kill();
    +      lineClear();
    +      lineHighlight(error);
    +      output
    +        .empty()
    +        .addClass('error')
    +        .text(error);
    +    }
    +    function loading() {
    +      lineClear();
    +      if (running) running.Kill();
    +      output.removeClass('error').text('Waiting for remote server...');
    +    }
    +    function run() {
    +      loading();
    +      running = transport.Run(
    +        body(),
    +        highlightOutput(PlaygroundOutput(output[0]))
    +      );
    +    }
    +
    +    function fmt() {
    +      loading();
    +      var data = { body: body() };
    +      if ($(opts.fmtImportEl).is(':checked')) {
    +        data['imports'] = 'true';
    +      }
    +      $.ajax('/fmt', {
    +        data: data,
    +        type: 'POST',
    +        dataType: 'json',
    +        success: function(data) {
    +          if (data.Error) {
    +            setError(data.Error);
    +          } else {
    +            setBody(data.Body);
    +            setError('');
    +          }
    +        },
    +      });
    +    }
    +
    +    var shareURL; // jQuery element to show the shared URL.
    +    var sharing = false; // true if there is a pending request.
    +    var shareCallbacks = [];
    +    function share(opt_callback) {
    +      if (opt_callback) shareCallbacks.push(opt_callback);
    +
    +      if (sharing) return;
    +      sharing = true;
    +
    +      var sharingData = body();
    +      $.ajax('/share', {
    +        processData: false,
    +        data: sharingData,
    +        type: 'POST',
    +        contentType: 'text/plain; charset=utf-8',
    +        complete: function(xhr) {
    +          sharing = false;
    +          if (xhr.status != 200) {
    +            alert('Server error; try again.');
    +            return;
    +          }
    +          if (opts.shareRedirect) {
    +            window.location = opts.shareRedirect + xhr.responseText;
    +          }
    +          var path = '/p/' + xhr.responseText;
    +          var url = origin(window.location) + path;
    +
    +          for (var i = 0; i < shareCallbacks.length; i++) {
    +            shareCallbacks[i](url);
    +          }
    +          shareCallbacks = [];
    +
    +          if (shareURL) {
    +            shareURL
    +              .show()
    +              .val(url)
    +              .focus()
    +              .select();
    +
    +            if (rewriteHistory) {
    +              var historyData = { code: sharingData };
    +              window.history.pushState(historyData, '', path);
    +              pushedEmpty = false;
    +            }
    +          }
    +        },
    +      });
    +    }
    +
    +    $(opts.runEl).click(run);
    +    $(opts.fmtEl).click(fmt);
    +
    +    if (
    +      opts.shareEl !== null &&
    +      (opts.shareURLEl !== null || opts.shareRedirect !== null)
    +    ) {
    +      if (opts.shareURLEl) {
    +        shareURL = $(opts.shareURLEl).hide();
    +      }
    +      $(opts.shareEl).click(function() {
    +        share();
    +      });
    +    }
    +
    +    if (opts.toysEl !== null) {
    +      $(opts.toysEl).bind('change', function() {
    +        var toy = $(this).val();
    +        $.ajax('/doc/play/' + toy, {
    +          processData: false,
    +          type: 'GET',
    +          complete: function(xhr) {
    +            if (xhr.status != 200) {
    +              alert('Server error; try again.');
    +              return;
    +            }
    +            setBody(xhr.responseText);
    +          },
    +        });
    +      });
    +    }
    +  }
    +
    +  window.playground = playground;
    +})();
    +// Copyright 2012 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +function initPlayground(transport) {
    +  'use strict';
    +
    +  function text(node) {
    +    var s = '';
    +    for (var i = 0; i < node.childNodes.length; i++) {
    +      var n = node.childNodes[i];
    +      if (n.nodeType === 1) {
    +        if (n.tagName === 'BUTTON') continue;
    +        if (n.tagName === 'SPAN' && n.className === 'number') continue;
    +        if (n.tagName === 'DIV' || n.tagName === 'BR' || n.tagName === 'PRE') {
    +          s += '\n';
    +        }
    +        s += text(n);
    +        continue;
    +      }
    +      if (n.nodeType === 3) {
    +        s += n.nodeValue;
    +      }
    +    }
    +    return s.replace('\xA0', ' '); // replace non-breaking spaces
    +  }
    +
    +  // When presenter notes are enabled, the index passed
    +  // here will identify the playground to be synced
    +  function init(code, index) {
    +    var output = document.createElement('div');
    +    var outpre = document.createElement('pre');
    +    var running;
    +
    +    if ($ && $(output).resizable) {
    +      $(output).resizable({
    +        handles: 'n,w,nw',
    +        minHeight: 27,
    +        minWidth: 135,
    +        maxHeight: 608,
    +        maxWidth: 990,
    +      });
    +    }
    +
    +    function onKill() {
    +      if (running) running.Kill();
    +      if (window.notesEnabled) updatePlayStorage('onKill', index);
    +    }
    +
    +    function onRun(e) {
    +      var sk = e.shiftKey || localStorage.getItem('play-shiftKey') === 'true';
    +      if (running) running.Kill();
    +      output.style.display = 'block';
    +      outpre.textContent = '';
    +      run1.style.display = 'none';
    +      var options = { Race: sk };
    +      running = transport.Run(text(code), PlaygroundOutput(outpre), options);
    +      if (window.notesEnabled) updatePlayStorage('onRun', index, e);
    +    }
    +
    +    function onClose() {
    +      if (running) running.Kill();
    +      output.style.display = 'none';
    +      run1.style.display = 'inline-block';
    +      if (window.notesEnabled) updatePlayStorage('onClose', index);
    +    }
    +
    +    if (window.notesEnabled) {
    +      playgroundHandlers.onRun.push(onRun);
    +      playgroundHandlers.onClose.push(onClose);
    +      playgroundHandlers.onKill.push(onKill);
    +    }
    +
    +    var run1 = document.createElement('button');
    +    run1.textContent = 'Run';
    +    run1.className = 'run';
    +    run1.addEventListener('click', onRun, false);
    +    var run2 = document.createElement('button');
    +    run2.className = 'run';
    +    run2.textContent = 'Run';
    +    run2.addEventListener('click', onRun, false);
    +    var kill = document.createElement('button');
    +    kill.className = 'kill';
    +    kill.textContent = 'Kill';
    +    kill.addEventListener('click', onKill, false);
    +    var close = document.createElement('button');
    +    close.className = 'close';
    +    close.textContent = 'Close';
    +    close.addEventListener('click', onClose, false);
    +
    +    var button = document.createElement('div');
    +    button.classList.add('buttons');
    +    button.appendChild(run1);
    +    // Hack to simulate insertAfter
    +    code.parentNode.insertBefore(button, code.nextSibling);
    +
    +    var buttons = document.createElement('div');
    +    buttons.classList.add('buttons');
    +    buttons.appendChild(run2);
    +    buttons.appendChild(kill);
    +    buttons.appendChild(close);
    +
    +    output.classList.add('output');
    +    output.appendChild(buttons);
    +    output.appendChild(outpre);
    +    output.style.display = 'none';
    +    code.parentNode.insertBefore(output, button.nextSibling);
    +  }
    +
    +  var play = document.querySelectorAll('div.playground');
    +  for (var i = 0; i < play.length; i++) {
    +    init(play[i], i);
    +  }
    +}
    +
    +initPlayground(new SocketTransport());
    diff --git a/2022/09/02/taurus/go_at_scale_files/slides.js b/2022/09/02/taurus/go_at_scale_files/slides.js
    new file mode 100644
    index 0000000..7c1229e
    --- /dev/null
    +++ b/2022/09/02/taurus/go_at_scale_files/slides.js
    @@ -0,0 +1,635 @@
    +// Copyright 2012 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +var PERMANENT_URL_PREFIX = '/static/';
    +
    +var SLIDE_CLASSES = ['far-past', 'past', 'current', 'next', 'far-next'];
    +
    +var PM_TOUCH_SENSITIVITY = 15;
    +
    +var curSlide;
    +
    +/* ---------------------------------------------------------------------- */
    +/* classList polyfill by Eli Grey
    + * (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */
    +
    +if (
    +  typeof document !== 'undefined' &&
    +  !('classList' in document.createElement('a'))
    +) {
    +  (function(view) {
    +    var classListProp = 'classList',
    +      protoProp = 'prototype',
    +      elemCtrProto = (view.HTMLElement || view.Element)[protoProp],
    +      objCtr = Object;
    +    (strTrim =
    +      String[protoProp].trim ||
    +      function() {
    +        return this.replace(/^\s+|\s+$/g, '');
    +      }),
    +      (arrIndexOf =
    +        Array[protoProp].indexOf ||
    +        function(item) {
    +          for (var i = 0, len = this.length; i < len; i++) {
    +            if (i in this && this[i] === item) {
    +              return i;
    +            }
    +          }
    +          return -1;
    +        }),
    +      // Vendors: please allow content code to instantiate DOMExceptions
    +      (DOMEx = function(type, message) {
    +        this.name = type;
    +        this.code = DOMException[type];
    +        this.message = message;
    +      }),
    +      (checkTokenAndGetIndex = function(classList, token) {
    +        if (token === '') {
    +          throw new DOMEx(
    +            'SYNTAX_ERR',
    +            'An invalid or illegal string was specified'
    +          );
    +        }
    +        if (/\s/.test(token)) {
    +          throw new DOMEx(
    +            'INVALID_CHARACTER_ERR',
    +            'String contains an invalid character'
    +          );
    +        }
    +        return arrIndexOf.call(classList, token);
    +      }),
    +      (ClassList = function(elem) {
    +        var trimmedClasses = strTrim.call(elem.className),
    +          classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [];
    +        for (var i = 0, len = classes.length; i < len; i++) {
    +          this.push(classes[i]);
    +        }
    +        this._updateClassName = function() {
    +          elem.className = this.toString();
    +        };
    +      }),
    +      (classListProto = ClassList[protoProp] = []),
    +      (classListGetter = function() {
    +        return new ClassList(this);
    +      });
    +    // Most DOMException implementations don't allow calling DOMException's toString()
    +    // on non-DOMExceptions. Error's toString() is sufficient here.
    +    DOMEx[protoProp] = Error[protoProp];
    +    classListProto.item = function(i) {
    +      return this[i] || null;
    +    };
    +    classListProto.contains = function(token) {
    +      token += '';
    +      return checkTokenAndGetIndex(this, token) !== -1;
    +    };
    +    classListProto.add = function(token) {
    +      token += '';
    +      if (checkTokenAndGetIndex(this, token) === -1) {
    +        this.push(token);
    +        this._updateClassName();
    +      }
    +    };
    +    classListProto.remove = function(token) {
    +      token += '';
    +      var index = checkTokenAndGetIndex(this, token);
    +      if (index !== -1) {
    +        this.splice(index, 1);
    +        this._updateClassName();
    +      }
    +    };
    +    classListProto.toggle = function(token) {
    +      token += '';
    +      if (checkTokenAndGetIndex(this, token) === -1) {
    +        this.add(token);
    +      } else {
    +        this.remove(token);
    +      }
    +    };
    +    classListProto.toString = function() {
    +      return this.join(' ');
    +    };
    +
    +    if (objCtr.defineProperty) {
    +      var classListPropDesc = {
    +        get: classListGetter,
    +        enumerable: true,
    +        configurable: true,
    +      };
    +      try {
    +        objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
    +      } catch (ex) {
    +        // IE 8 doesn't support enumerable:true
    +        if (ex.number === -0x7ff5ec54) {
    +          classListPropDesc.enumerable = false;
    +          objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
    +        }
    +      }
    +    } else if (objCtr[protoProp].__defineGetter__) {
    +      elemCtrProto.__defineGetter__(classListProp, classListGetter);
    +    }
    +  })(self);
    +}
    +/* ---------------------------------------------------------------------- */
    +
    +/* Slide movement */
    +
    +function hideHelpText() {
    +  document.getElementById('help').style.display = 'none';
    +}
    +
    +function getSlideEl(no) {
    +  if (no < 0 || no >= slideEls.length) {
    +    return null;
    +  } else {
    +    return slideEls[no];
    +  }
    +}
    +
    +function updateSlideClass(slideNo, className) {
    +  var el = getSlideEl(slideNo);
    +
    +  if (!el) {
    +    return;
    +  }
    +
    +  if (className) {
    +    el.classList.add(className);
    +  }
    +
    +  for (var i in SLIDE_CLASSES) {
    +    if (className != SLIDE_CLASSES[i]) {
    +      el.classList.remove(SLIDE_CLASSES[i]);
    +    }
    +  }
    +}
    +
    +function updateSlides() {
    +  if (window.trackPageview) window.trackPageview();
    +
    +  for (var i = 0; i < slideEls.length; i++) {
    +    switch (i) {
    +      case curSlide - 2:
    +        updateSlideClass(i, 'far-past');
    +        break;
    +      case curSlide - 1:
    +        updateSlideClass(i, 'past');
    +        break;
    +      case curSlide:
    +        updateSlideClass(i, 'current');
    +        break;
    +      case curSlide + 1:
    +        updateSlideClass(i, 'next');
    +        break;
    +      case curSlide + 2:
    +        updateSlideClass(i, 'far-next');
    +        break;
    +      default:
    +        updateSlideClass(i);
    +        break;
    +    }
    +  }
    +
    +  triggerLeaveEvent(curSlide - 1);
    +  triggerEnterEvent(curSlide);
    +
    +  window.setTimeout(function() {
    +    // Hide after the slide
    +    disableSlideFrames(curSlide - 2);
    +  }, 301);
    +
    +  enableSlideFrames(curSlide - 1);
    +  enableSlideFrames(curSlide + 2);
    +
    +  updateHash();
    +}
    +
    +function prevSlide() {
    +  hideHelpText();
    +  if (curSlide > 0) {
    +    curSlide--;
    +
    +    updateSlides();
    +  }
    +
    +  if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide);
    +}
    +
    +function nextSlide() {
    +  hideHelpText();
    +  if (curSlide < slideEls.length - 1) {
    +    curSlide++;
    +
    +    updateSlides();
    +  }
    +
    +  if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide);
    +}
    +
    +/* Slide events */
    +
    +function triggerEnterEvent(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var onEnter = el.getAttribute('onslideenter');
    +  if (onEnter) {
    +    new Function(onEnter).call(el);
    +  }
    +
    +  var evt = document.createEvent('Event');
    +  evt.initEvent('slideenter', true, true);
    +  evt.slideNumber = no + 1; // Make it readable
    +
    +  el.dispatchEvent(evt);
    +}
    +
    +function triggerLeaveEvent(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var onLeave = el.getAttribute('onslideleave');
    +  if (onLeave) {
    +    new Function(onLeave).call(el);
    +  }
    +
    +  var evt = document.createEvent('Event');
    +  evt.initEvent('slideleave', true, true);
    +  evt.slideNumber = no + 1; // Make it readable
    +
    +  el.dispatchEvent(evt);
    +}
    +
    +/* Touch events */
    +
    +function handleTouchStart(event) {
    +  if (event.touches.length == 1) {
    +    touchDX = 0;
    +    touchDY = 0;
    +
    +    touchStartX = event.touches[0].pageX;
    +    touchStartY = event.touches[0].pageY;
    +
    +    document.body.addEventListener('touchmove', handleTouchMove, true);
    +    document.body.addEventListener('touchend', handleTouchEnd, true);
    +  }
    +}
    +
    +function handleTouchMove(event) {
    +  if (event.touches.length > 1) {
    +    cancelTouch();
    +  } else {
    +    touchDX = event.touches[0].pageX - touchStartX;
    +    touchDY = event.touches[0].pageY - touchStartY;
    +    event.preventDefault();
    +  }
    +}
    +
    +function handleTouchEnd(event) {
    +  var dx = Math.abs(touchDX);
    +  var dy = Math.abs(touchDY);
    +
    +  if (dx > PM_TOUCH_SENSITIVITY && dy < (dx * 2) / 3) {
    +    if (touchDX > 0) {
    +      prevSlide();
    +    } else {
    +      nextSlide();
    +    }
    +  }
    +
    +  cancelTouch();
    +}
    +
    +function cancelTouch() {
    +  document.body.removeEventListener('touchmove', handleTouchMove, true);
    +  document.body.removeEventListener('touchend', handleTouchEnd, true);
    +}
    +
    +/* Preloading frames */
    +
    +function disableSlideFrames(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var frames = el.getElementsByTagName('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    disableFrame(frame);
    +  }
    +}
    +
    +function enableSlideFrames(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var frames = el.getElementsByTagName('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    enableFrame(frame);
    +  }
    +}
    +
    +function disableFrame(frame) {
    +  frame.src = 'about:blank';
    +}
    +
    +function enableFrame(frame) {
    +  var src = frame._src;
    +
    +  if (frame.src != src && src != 'about:blank') {
    +    frame.src = src;
    +  }
    +}
    +
    +function setupFrames() {
    +  var frames = document.querySelectorAll('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    frame._src = frame.src;
    +    disableFrame(frame);
    +  }
    +
    +  enableSlideFrames(curSlide);
    +  enableSlideFrames(curSlide + 1);
    +  enableSlideFrames(curSlide + 2);
    +}
    +
    +function setupInteraction() {
    +  /* Clicking and tapping */
    +
    +  var el = document.createElement('div');
    +  el.className = 'slide-area';
    +  el.id = 'prev-slide-area';
    +  el.addEventListener('click', prevSlide, false);
    +  document.querySelector('section.slides').appendChild(el);
    +
    +  var el = document.createElement('div');
    +  el.className = 'slide-area';
    +  el.id = 'next-slide-area';
    +  el.addEventListener('click', nextSlide, false);
    +  document.querySelector('section.slides').appendChild(el);
    +
    +  /* Swiping */
    +
    +  document.body.addEventListener('touchstart', handleTouchStart, false);
    +}
    +
    +/* Hash functions */
    +
    +function getCurSlideFromHash() {
    +  var slideNo = parseInt(location.hash.substr(1));
    +
    +  if (slideNo) {
    +    curSlide = slideNo - 1;
    +  } else {
    +    curSlide = 0;
    +  }
    +}
    +
    +function updateHash() {
    +  location.replace('#' + (curSlide + 1));
    +}
    +
    +/* Event listeners */
    +
    +function handleBodyKeyDown(event) {
    +  // If we're in a code element, only handle pgup/down.
    +  var inCode = event.target.classList.contains('code');
    +
    +  switch (event.keyCode) {
    +    case 78: // 'N' opens presenter notes window
    +      if (!inCode && notesEnabled) toggleNotesWindow();
    +      break;
    +    case 72: // 'H' hides the help text
    +    case 27: // escape key
    +      if (!inCode) hideHelpText();
    +      break;
    +
    +    case 39: // right arrow
    +    case 13: // Enter
    +    case 32: // space
    +      if (inCode) break;
    +    case 34: // PgDn
    +      nextSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 37: // left arrow
    +    case 8: // Backspace
    +      if (inCode) break;
    +    case 33: // PgUp
    +      prevSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 40: // down arrow
    +      if (inCode) break;
    +      nextSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 38: // up arrow
    +      if (inCode) break;
    +      prevSlide();
    +      event.preventDefault();
    +      break;
    +  }
    +}
    +
    +function scaleSmallViewports() {
    +  var el = document.querySelector('section.slides');
    +  var transform = '';
    +  var sWidthPx = 1250;
    +  var sHeightPx = 750;
    +  var sAspectRatio = sWidthPx / sHeightPx;
    +  var wAspectRatio = window.innerWidth / window.innerHeight;
    +
    +  if (wAspectRatio <= sAspectRatio && window.innerWidth < sWidthPx) {
    +    transform = 'scale(' + window.innerWidth / sWidthPx + ')';
    +  } else if (window.innerHeight < sHeightPx) {
    +    transform = 'scale(' + window.innerHeight / sHeightPx + ')';
    +  }
    +  el.style.transform = transform;
    +}
    +
    +function addEventListeners() {
    +  document.addEventListener('keydown', handleBodyKeyDown, false);
    +  var resizeTimeout;
    +  window.addEventListener('resize', function() {
    +    // throttle resize events
    +    window.clearTimeout(resizeTimeout);
    +    resizeTimeout = window.setTimeout(function() {
    +      resizeTimeout = null;
    +      scaleSmallViewports();
    +    }, 50);
    +  });
    +
    +  // Force reset transform property of section.slides when printing page.
    +  // Use both onbeforeprint and matchMedia for compatibility with different browsers.
    +  var beforePrint = function() {
    +    var el = document.querySelector('section.slides');
    +    el.style.transform = '';
    +  };
    +  window.onbeforeprint = beforePrint;
    +  if (window.matchMedia) {
    +    var mediaQueryList = window.matchMedia('print');
    +    mediaQueryList.addListener(function(mql) {
    +      if (mql.matches) beforePrint();
    +    });
    +  }
    +}
    +
    +/* Initialization */
    +
    +function addFontStyle() {
    +  var el = document.createElement('link');
    +  el.rel = 'stylesheet';
    +  el.type = 'text/css';
    +  el.href =
    +    '//fonts.googleapis.com/css?family=' +
    +    'Open+Sans:regular,semibold,italic,italicsemibold|Droid+Sans+Mono';
    +
    +  document.body.appendChild(el);
    +}
    +
    +function addGeneralStyle() {
    +  var el = document.createElement('link');
    +  el.rel = 'stylesheet';
    +  el.type = 'text/css';
    +  el.href = PERMANENT_URL_PREFIX + 'styles.css';
    +  document.body.appendChild(el);
    +
    +  var el = document.createElement('meta');
    +  el.name = 'viewport';
    +  el.content = 'width=device-width,height=device-height,initial-scale=1';
    +  document.querySelector('head').appendChild(el);
    +
    +  var el = document.createElement('meta');
    +  el.name = 'apple-mobile-web-app-capable';
    +  el.content = 'yes';
    +  document.querySelector('head').appendChild(el);
    +
    +  scaleSmallViewports();
    +}
    +
    +function handleDomLoaded() {
    +  slideEls = document.querySelectorAll('section.slides > article');
    +
    +  setupFrames();
    +
    +  addFontStyle();
    +  addGeneralStyle();
    +  addEventListeners();
    +
    +  updateSlides();
    +
    +  setupInteraction();
    +
    +  if (
    +    window.location.hostname == 'localhost' ||
    +    window.location.hostname == '127.0.0.1' ||
    +    window.location.hostname == '::1'
    +  ) {
    +    hideHelpText();
    +  }
    +
    +  document.body.classList.add('loaded');
    +
    +  setupNotesSync();
    +}
    +
    +function initialize() {
    +  getCurSlideFromHash();
    +
    +  if (window['_DEBUG']) {
    +    PERMANENT_URL_PREFIX = '../';
    +  }
    +
    +  if (window['_DCL']) {
    +    handleDomLoaded();
    +  } else {
    +    document.addEventListener('DOMContentLoaded', handleDomLoaded, false);
    +  }
    +}
    +
    +// If ?debug exists then load the script relative instead of absolute
    +if (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) {
    +  document.addEventListener(
    +    'DOMContentLoaded',
    +    function() {
    +      // Avoid missing the DomContentLoaded event
    +      window['_DCL'] = true;
    +    },
    +    false
    +  );
    +
    +  window['_DEBUG'] = true;
    +  var script = document.createElement('script');
    +  script.type = 'text/javascript';
    +  script.src = '../slides.js';
    +  var s = document.getElementsByTagName('script')[0];
    +  s.parentNode.insertBefore(script, s);
    +
    +  // Remove this script
    +  s.parentNode.removeChild(s);
    +} else {
    +  initialize();
    +}
    +
    +/* Synchronize windows when notes are enabled */
    +
    +function setupNotesSync() {
    +  if (!notesEnabled) return;
    +
    +  function setupPlayResizeSync() {
    +    var out = document.getElementsByClassName('output');
    +    for (var i = 0; i < out.length; i++) {
    +      $(out[i]).bind('resize', function(event) {
    +        if ($(event.target).hasClass('ui-resizable')) {
    +          localStorage.setItem('play-index', i);
    +          localStorage.setItem('output-style', out[i].style.cssText);
    +        }
    +      });
    +    }
    +  }
    +  function setupPlayCodeSync() {
    +    var play = document.querySelectorAll('div.playground');
    +    for (var i = 0; i < play.length; i++) {
    +      play[i].addEventListener('input', inputHandler, false);
    +
    +      function inputHandler(e) {
    +        localStorage.setItem('play-index', i);
    +        localStorage.setItem('play-code', e.target.innerHTML);
    +      }
    +    }
    +  }
    +
    +  setupPlayCodeSync();
    +  setupPlayResizeSync();
    +  localStorage.setItem(destSlideKey(), curSlide);
    +  window.addEventListener('storage', updateOtherWindow, false);
    +}
    +
    +// An update to local storage is caught only by the other window
    +// The triggering window does not handle any sync actions
    +function updateOtherWindow(e) {
    +  // Ignore remove storage events which are not meant to update the other window
    +  var isRemoveStorageEvent = !e.newValue;
    +  if (isRemoveStorageEvent) return;
    +
    +  var destSlide = localStorage.getItem(destSlideKey());
    +  while (destSlide > curSlide) {
    +    nextSlide();
    +  }
    +  while (destSlide < curSlide) {
    +    prevSlide();
    +  }
    +
    +  updatePlay(e);
    +  updateNotes();
    +}
    diff --git a/2022/09/02/taurus/go_at_scale_files/styles.css b/2022/09/02/taurus/go_at_scale_files/styles.css
    new file mode 100644
    index 0000000..5edfde9
    --- /dev/null
    +++ b/2022/09/02/taurus/go_at_scale_files/styles.css
    @@ -0,0 +1,553 @@
    +@media screen {
    +  /* Framework */
    +  html {
    +    height: 100%;
    +  }
    +
    +  body {
    +    margin: 0;
    +    padding: 0;
    +
    +    display: block !important;
    +
    +    height: 100%;
    +    height: 100vh;
    +
    +    overflow: hidden;
    +
    +    background: rgb(215, 215, 215);
    +    background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -webkit-gradient(
    +      radial,
    +      50% 50%,
    +      0,
    +      50% 50%,
    +      500,
    +      from(rgb(240, 240, 240)),
    +      to(rgb(190, 190, 190))
    +    );
    +
    +    -webkit-font-smoothing: antialiased;
    +  }
    +
    +  .slides {
    +    width: 100%;
    +    height: 100%;
    +    left: 0;
    +    top: 0;
    +
    +    position: absolute;
    +
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +
    +  .slides > article {
    +    display: block;
    +
    +    position: absolute;
    +    overflow: hidden;
    +
    +    width: 900px;
    +    height: 700px;
    +
    +    left: 50%;
    +    top: 50%;
    +
    +    margin-left: -450px;
    +    margin-top: -350px;
    +
    +    padding: 40px 60px;
    +
    +    box-sizing: border-box;
    +    -o-box-sizing: border-box;
    +    -moz-box-sizing: border-box;
    +    -webkit-box-sizing: border-box;
    +
    +    border-radius: 10px;
    +    -o-border-radius: 10px;
    +    -moz-border-radius: 10px;
    +    -webkit-border-radius: 10px;
    +
    +    background-color: white;
    +
    +    border: 1px solid rgba(0, 0, 0, 0.3);
    +
    +    transition: transform 0.3s ease-out;
    +    -o-transition: -o-transform 0.3s ease-out;
    +    -moz-transition: -moz-transform 0.3s ease-out;
    +    -webkit-transition: -webkit-transform 0.3s ease-out;
    +  }
    +  .slides.layout-widescreen > article {
    +    margin-left: -550px;
    +    width: 1100px;
    +  }
    +  .slides.layout-faux-widescreen > article {
    +    margin-left: -550px;
    +    width: 1100px;
    +
    +    padding: 40px 160px;
    +  }
    +
    +  .slides.layout-widescreen > article:not(.nobackground):not(.biglogo),
    +  .slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) {
    +    background-position-x: 0, 840px;
    +  }
    +
    +  /* Clickable/tappable areas */
    +
    +  .slide-area {
    +    z-index: 1000;
    +
    +    position: absolute;
    +    left: 0;
    +    top: 0;
    +    width: 150px;
    +    height: 700px;
    +
    +    left: 50%;
    +    top: 50%;
    +
    +    cursor: pointer;
    +    margin-top: -350px;
    +
    +    tap-highlight-color: transparent;
    +    -o-tap-highlight-color: transparent;
    +    -moz-tap-highlight-color: transparent;
    +    -webkit-tap-highlight-color: transparent;
    +  }
    +  #prev-slide-area {
    +    margin-left: -550px;
    +  }
    +  #next-slide-area {
    +    margin-left: 400px;
    +  }
    +  .slides.layout-widescreen #prev-slide-area,
    +  .slides.layout-faux-widescreen #prev-slide-area {
    +    margin-left: -650px;
    +  }
    +  .slides.layout-widescreen #next-slide-area,
    +  .slides.layout-faux-widescreen #next-slide-area {
    +    margin-left: 500px;
    +  }
    +
    +  /* Slides */
    +
    +  .slides > article {
    +    display: none;
    +  }
    +  .slides > article.far-past {
    +    display: block;
    +    transform: translate(-2040px);
    +    -o-transform: translate(-2040px);
    +    -moz-transform: translate(-2040px);
    +    -webkit-transform: translate3d(-2040px, 0, 0);
    +  }
    +  .slides > article.past {
    +    display: block;
    +    transform: translate(-1020px);
    +    -o-transform: translate(-1020px);
    +    -moz-transform: translate(-1020px);
    +    -webkit-transform: translate3d(-1020px, 0, 0);
    +  }
    +  .slides > article.current {
    +    display: block;
    +    transform: translate(0);
    +    -o-transform: translate(0);
    +    -moz-transform: translate(0);
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +  .slides > article.next {
    +    display: block;
    +    transform: translate(1020px);
    +    -o-transform: translate(1020px);
    +    -moz-transform: translate(1020px);
    +    -webkit-transform: translate3d(1020px, 0, 0);
    +  }
    +  .slides > article.far-next {
    +    display: block;
    +    transform: translate(2040px);
    +    -o-transform: translate(2040px);
    +    -moz-transform: translate(2040px);
    +    -webkit-transform: translate3d(2040px, 0, 0);
    +  }
    +
    +  .slides.layout-widescreen > article.far-past,
    +  .slides.layout-faux-widescreen > article.far-past {
    +    display: block;
    +    transform: translate(-2260px);
    +    -o-transform: translate(-2260px);
    +    -moz-transform: translate(-2260px);
    +    -webkit-transform: translate3d(-2260px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.past,
    +  .slides.layout-faux-widescreen > article.past {
    +    display: block;
    +    transform: translate(-1130px);
    +    -o-transform: translate(-1130px);
    +    -moz-transform: translate(-1130px);
    +    -webkit-transform: translate3d(-1130px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.current,
    +  .slides.layout-faux-widescreen > article.current {
    +    display: block;
    +    transform: translate(0);
    +    -o-transform: translate(0);
    +    -moz-transform: translate(0);
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.next,
    +  .slides.layout-faux-widescreen > article.next {
    +    display: block;
    +    transform: translate(1130px);
    +    -o-transform: translate(1130px);
    +    -moz-transform: translate(1130px);
    +    -webkit-transform: translate3d(1130px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.far-next,
    +  .slides.layout-faux-widescreen > article.far-next {
    +    display: block;
    +    transform: translate(2260px);
    +    -o-transform: translate(2260px);
    +    -moz-transform: translate(2260px);
    +    -webkit-transform: translate3d(2260px, 0, 0);
    +  }
    +}
    +
    +@media print {
    +  /* Set page layout */
    +  @page {
    +    size: A4 landscape;
    +  }
    +
    +  body {
    +    display: block !important;
    +  }
    +
    +  .slides > article {
    +    display: block;
    +
    +    position: relative;
    +
    +    page-break-inside: never;
    +    page-break-after: always;
    +
    +    overflow: hidden;
    +  }
    +
    +  h2 {
    +    position: static !important;
    +    margin-top: 400px !important;
    +    margin-bottom: 100px !important;
    +  }
    +
    +  div.code {
    +    background: rgb(240, 240, 240);
    +  }
    +
    +  /* Add explicit links */
    +  a:link:after,
    +  a:visited:after {
    +    content: ' (' attr(href) ') ';
    +    font-size: 50%;
    +  }
    +
    +  #help {
    +    display: none;
    +    visibility: hidden;
    +  }
    +}
    +
    +/* Styles for slides */
    +
    +.slides > article {
    +  font-family: 'Open Sans', Arial, sans-serif;
    +
    +  color: black;
    +  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
    +
    +  font-size: 26px;
    +  line-height: 36px;
    +
    +  letter-spacing: -1px;
    +}
    +
    +b {
    +  font-weight: 600;
    +}
    +
    +a {
    +  color: rgb(0, 102, 204);
    +  text-decoration: none;
    +}
    +a:visited {
    +  color: rgba(0, 102, 204, 0.75);
    +}
    +a:hover {
    +  color: black;
    +}
    +
    +p {
    +  margin: 0;
    +  padding: 0;
    +
    +  margin-top: 20px;
    +}
    +p:first-child {
    +  margin-top: 0;
    +}
    +
    +h1 {
    +  font-size: 60px;
    +  line-height: 60px;
    +
    +  padding: 0;
    +  margin: 0;
    +  margin-top: 200px;
    +  margin-bottom: 5px;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -3px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +h2 {
    +  font-size: 45px;
    +  line-height: 45px;
    +
    +  position: absolute;
    +  bottom: 150px;
    +
    +  padding: 0;
    +  margin: 0;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -2px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +h3 {
    +  font-size: 30px;
    +  line-height: 36px;
    +
    +  padding: 0;
    +  margin: 0;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -1px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +ul {
    +  margin: 0;
    +  padding: 0;
    +  margin-top: 20px;
    +  margin-left: 1.5em;
    +}
    +li {
    +  padding: 0;
    +  margin: 0 0 0.5em 0;
    +}
    +
    +div.code {
    +  padding: 5px 10px;
    +  margin-top: 20px;
    +  margin-bottom: 20px;
    +  overflow: hidden;
    +
    +  background: rgb(240, 240, 240);
    +  border: 1px solid rgb(224, 224, 224);
    +}
    +pre {
    +  margin: 0;
    +  padding: 0;
    +
    +  font-family: 'Droid Sans Mono', 'Courier New', monospace;
    +  font-size: 18px;
    +  line-height: 24px;
    +  letter-spacing: -1px;
    +
    +  color: black;
    +}
    +
    +pre.numbers span:before {
    +  content: attr(num);
    +  margin-right: 1em;
    +  display: inline-block;
    +}
    +
    +code {
    +  font-size: 95%;
    +  font-family: 'Droid Sans Mono', 'Courier New', monospace;
    +
    +  color: black;
    +}
    +
    +article > .image,
    +article > .video {
    +  text-align: center;
    +  margin-top: 40px;
    +}
    +
    +article.background {
    +  background-size: contain;
    +  background-repeat: round;
    +}
    +
    +table {
    +  width: 100%;
    +  border-collapse: collapse;
    +  margin-top: 40px;
    +}
    +th {
    +  font-weight: 600;
    +  text-align: left;
    +}
    +td,
    +th {
    +  border: 1px solid rgb(224, 224, 224);
    +  padding: 5px 10px;
    +  vertical-align: top;
    +}
    +
    +p.link {
    +  margin-left: 20px;
    +}
    +
    +.pagenumber {
    +  color: #8c8c8c;
    +  font-size: 75%;
    +  position: absolute;
    +  bottom: 0px;
    +  right: 10px;
    +}
    +
    +/* Code */
    +div.code {
    +  outline: 0px solid transparent;
    +}
    +div.playground {
    +  position: relative;
    +}
    +div.output {
    +  position: absolute;
    +  left: 50%;
    +  top: 50%;
    +  right: 40px;
    +  bottom: 40px;
    +  background: #202020;
    +  padding: 5px 10px;
    +  z-index: 2;
    +
    +  border-radius: 10px;
    +  -o-border-radius: 10px;
    +  -moz-border-radius: 10px;
    +  -webkit-border-radius: 10px;
    +}
    +div.output pre {
    +  margin: 0;
    +  padding: 0;
    +  background: none;
    +  border: none;
    +  width: 100%;
    +  height: 100%;
    +  overflow: auto;
    +}
    +div.output .stdout,
    +div.output pre {
    +  color: #e6e6e6;
    +}
    +div.output .stderr,
    +div.output .error {
    +  color: rgb(255, 200, 200);
    +}
    +div.output .system,
    +div.output .exit {
    +  color: rgb(255, 230, 120);
    +}
    +.buttons {
    +  position: relative;
    +  float: right;
    +  top: -60px;
    +  right: 10px;
    +}
    +div.output .buttons {
    +  position: absolute;
    +  float: none;
    +  top: auto;
    +  right: 5px;
    +  bottom: 5px;
    +}
    +
    +/* Presenter details */
    +.presenter {
    +  margin-top: 20px;
    +}
    +.presenter p,
    +.presenter .link {
    +  margin: 0;
    +  font-size: 28px;
    +  line-height: 1.2em;
    +}
    +
    +/* Output resize details */
    +.ui-resizable-handle {
    +  position: absolute;
    +}
    +.ui-resizable-n {
    +  cursor: n-resize;
    +  height: 7px;
    +  width: 100%;
    +  top: -5px;
    +  left: 0;
    +}
    +.ui-resizable-w {
    +  cursor: w-resize;
    +  width: 7px;
    +  left: -5px;
    +  top: 0;
    +  height: 100%;
    +}
    +.ui-resizable-nw {
    +  cursor: nw-resize;
    +  width: 9px;
    +  height: 9px;
    +  left: -5px;
    +  top: -5px;
    +}
    +iframe {
    +  border: none;
    +}
    +figcaption {
    +  color: #666;
    +  text-align: center;
    +  font-size: 0.75em;
    +}
    +
    +#help {
    +  font-family: 'Open Sans', Arial, sans-serif;
    +  text-align: center;
    +  color: white;
    +  background: #000;
    +  opacity: 0.5;
    +  position: fixed;
    +  bottom: 25px;
    +  left: 50px;
    +  right: 50px;
    +  padding: 20px;
    +
    +  border-radius: 10px;
    +  -o-border-radius: 10px;
    +  -moz-border-radius: 10px;
    +  -webkit-border-radius: 10px;
    +}
    diff --git a/2022/09/02/taurus/go_at_scale_files/trace-visuals.png b/2022/09/02/taurus/go_at_scale_files/trace-visuals.png
    new file mode 100644
    index 0000000..bfd53ec
    Binary files /dev/null and b/2022/09/02/taurus/go_at_scale_files/trace-visuals.png differ
    diff --git a/2022/09/02/taurus/goatscale.slide b/2022/09/02/taurus/goatscale.slide
    new file mode 100644
    index 0000000..ca5c6d7
    --- /dev/null
    +++ b/2022/09/02/taurus/goatscale.slide
    @@ -0,0 +1,166 @@
    +# Go, at scale
    +Tags: go, high-performance, productivity
    +
    +Emmanuel T Odeke
    +Orijtech, Inc.
    +Fri 2 Sep 2022
    +emmanuel@orijtech.com
    +https://go.orijtech.com
    +@odeke_et
    +
    +## Go, at scale
    +
    +## About this talk
    +- Go, at scale, so you can go to scale!
    +- From this talk, you should have the tools to get web services up & running in production & also able to observe them & improve your services, plus profile & test them
    +- Using Go to enhance and take your productivity to hyperscale development
    +- Scale: elastic growth/grace with the magnitude and intensity of a problem
    +- Scale to mean team & engineering productivity from 0 to infinity
    +- From startups to Fortune 500 companies: Go is a suitable tool to build production services
    +- Wielding the power of Go can happen with the right focus, humility and urge to learn without pollution of ideas from past technologies
    +- Open minds and the need for speed & productivity!
    +- Lessons from running backend services at companies of all sizes: startup to Fortune 10 companies
    +
    +## About myself
    +- Emmanuel T Odeke
    +- Building [Orijtech, Inc](https://orijtech.com/)
    +- Enjoy learning and solving problems; I am mostly self taught
    +- Always learning
    +- Avid open source producer and consumer
    +- Core contributor and leader on the [Go programming language](https://golang.org/)
    +- Core contributor and leader on [OpenCensus](https://opencensus.io/) and [OpenTelemetry](https://opentelemetry.io/)
    +- Always learning, and enjoy solving problems!
    +- Building critical and high performance software engineering tools like Go, static analyzers, CI/CD infrastructure, databases, observability infrastructure, security infrastructure
    +
    +## What is Go?
    +- Go is a statically typed, statically linked programming language pioneered at Google
    +- Brain child of Robert Griesemer, Rob Pike, Ken Thompson who conceptualized it allegedly while waiting for C++ builds to complete
    +- Go Co-authors also acknowledged as Russ Cox, Ian Lance Taylor
    +- Hashtag is "golang", language is "Go", website "golang.org"
    +- Go is an expressive language built with principles of pragmatism and engineering productivity
    +- Highly concurrent, modern to help utilize all the cores of modern machines
    +- No need to sweat with pthreads directly nor re-inventing own scheduling yet getting it wrong
    +- The undisputed language of the cloud!
    +
    +## Goroutine dispatched
    +
    +.play uncancellable.go
    +
    +## What's troublesome in that code?
    +- Non-determinism in goroutines happens when the goroutine's course cannot be determined by external conditions nor can its termination be guaranteed
    +- ** commentary in conversation in presentation **
    +
    +## Plumb with context
    +- Context allows you to check that the context is still alive hence you can carry on work
    +- Useful in situations such as an HTTP request's processing being stopped after a client goes away or when no longer needed
    +- Multiplex on a channel with Go keyword "select"
    +
    +## Plumb with context
    +.play cancellable1.go
    +
    +## Plumb with context: multiplex on channels with "select"
    +.play cancellable2.go
    +
    +## HTTP request hedging
    +- A powerful concept used to help with increasing reliability of backend services
    +- Popularized by Google's Jeff Dean in [The Tail at scale](https://cacm.acm.org/magazines/2013/2/160173-the-tail-at-scale/fulltext)
    +- If a service keeps failing, try again with N requests and for the first that returns early, cancel all the rest
    +- Trivial concept to implement natively in Go using [net/http.NewRequestWithContext](https://golang.org/pkg/net/http/#NewRequestWithContext)
    +- Send out N requests derived from the same context `ctx`, get the first successful result and then cancel the context after parsing successfully from the working request
    +- Keeps the machines well utilized!
    +- Just by taking in a context.Context as well as multiplexing on a channel for results, you can race HTTP requests!
    +- With first class features in Go, you now have the power to build prolific features!
    +
    +## Supply chain security
    +
    +## go.mod is a great forensic tool
    +- go.mod and go.sum are 2 distinct files generated and used by the Go build system since Go1.15
    +- Not just for decoration, they are an auditable trail of dependencies
    +- Software Bill of Materials (SBOM) integrated first class into the language
    +- Useful in pining dependencies but also in supply chain analysis
    +- Read more about Go Modules at https://go.dev/ref/mod
    +- Kudos to the Go security team for being this thoughtful!
    +
    +
    +## Go networking & Remote Procedure Call (RPC) libraries
    +- [net/http](https://golang.org/pkg/net/http) -- basis for majority of networking libraries and sufficient for most networking purposes
    +- [gRPC library](https://google.golang.org/grpc) google.golang.org/grpc
    +- [net/rpc](https://golang.org/pkg/net/rpc) -- deprecated though, please use gRPC
    +- [Apache Thrift](https://pkg.go.dev/github.com/apache/thrift/lib/go/thrift)
    +
    +## Build microservices
    +
    +## Take advantage of Go's excellent networking to build microservices
    +- Monoliths can be useful but they curtail creativity and development speed because teams can't experiment, rigorously test components and isolate failures when trouble occurs
    +- Go has excellent networking libraries
    +- Look at the package net/http
    +- In less than 10 lines, we can make a production worthy server
    +
    +.play goprodserver.go
    +
    +## Tack on HTTPS with Let's Encrypt
    +In 14 lines, we can use free TLS certificates from the gracious and awesome Let's Encrypt!
    +
    +.play goprodserver_lets_encrypt.go
    +
    +## Observability
    +- Observability is the ability to examine the internal states of a system by checking on vital/critical representative signals
    +- Think of what happens what you visit the doctor's office: instead of dissecting you just to figure out what's causing your headache, they'll firstly ask diagnosing questions and take tests
    +- Comes from control theory and Linear Algebra in which if an equation is linearly solveable, you understand the system
    +- For backend applications, we look at function and user defined traces, quantifiable metrics such as throughput (requests per second), memory consumed, file descriptors open, logs
    +- Need a reliable data cruncher and techniques to sift through large amounts of data
    +
    +## Sample web app
    +
    +
    +
    +## Observability
    +
    +
    +## Observability libraries
    +- OpenCensus Go (stable package)
    +- OpenTelemetry Go (recommended newer version)
    +- Recommended: [my talk at GoSF: Planet Scale observability with OpenCensus](https://orijtech.github.io/talks/2018/07/18/gosf/gosf.htm)
    +
    +## Observability results
    +## Testing
    +
    +## Write packages that are self contained and testable
    +- Business logic should be isolated in packages that can be well tested
    +- Use Go's testing and coverage tools: `go test`, or `go test -coverprofile=out.cover && go tool cover -html=out.cover`
    +- Can CPU & memory profile them using [runtime/pprof](https://golang.org/pkg/runtime/pprof) in tests too with: `go test -cpuprofile=prof.cpu -memprofile=prof.mem` and then use `go tool pprof prof.cpu` for CPU profiling examinations, or `go tool pprof prof.mem` for memory profiling examinations
    +- Runtime tracing can be performed using the [runtime/trace](https://golang.org/pkg/runtime/trace) package
    +
    +## Effectively test out your services using finesse of the language
    +- You should be able to test out your packages individually and aim for 100% coverage if possible
    +- Even testing out HTTP handlers and servers is possible, please see [net/http/httptest](https://pkg.go.dev/net/http/httptest)
    +- Study up on [Taming net/http by Orijtech Inc](https://medium.com/orijtech-developers/taming-net-http-b946edfda562)
    +- First class fuzzing
    +- Incorporate fuzzers and run them continuously, please see ossfuzz
    +
    +## Go security releases
    +- Please update your Go releases often, keep in touch with the Go security mailing list at https://groups.google.com/g/golang-announce/
    +- Update often, lots of gems and hardwork from the security team as well as the general Go releases
    +- Most of the time, upgrading to the latest version gets you speed and feature improvements
    +- Figure out a way of pushing out Go releases within your company
    +- Take advantage of continuous integration and deployment (CI/CD) with the latest releases of Go
    +- File bugs for oddities you might encounter!
    +
    +## Go Community
    +- Go's community is welcoming, diverse, creative, of all kinds of sizes from startups
    +- Take a look at the landing page [https://go.dev/](https://go.dev/)
    +- File issues and check out [issues](https://golang.org/issues)
    +- Contribute to Go! Fascinating way to learn, get in touch, give back, grow further, get needs met, have fun etc
    +- Attend Go conferences, network for example [Gophercon 2022](https://www.gophercon.com/) for which [Orijtech Inc we are a continued proud sponsor :-)](https://www.gophercon.com/page/2035126/sponsors)
    +- Go wiki at [https://github.com/golang/go/wiki](https://github.com/golang/go/wiki)
    +- [Visit the Go community listing showing: Go Forum, Gopher Slack, r/golang, Twitter, StackOverflow pages etc](https://github.com/golang/go/wiki#the-go-community)
    +
    +## References
    +- [Planet scale observability with OpenCensus: Emmanuel Odeke, Orijtech Inc:: July 18th 2018, Go San Francisco](https://orijtech.github.io/talks/2018/07/18/gosf/gosf.htm)
    +- [The Tail at scale: Jeffrey Dean, Luiz André Barroso, Google Inc:: February 2013, ACM Publications](https://cacm.acm.org/magazines/2013/2/160173-the-tail-at-scale/fulltext) 
    +- [The Go Programming Language and Environment: Russ Cox, Robert Griesemer, Rob Pike, Ian Lance Taylor, Ken Thompson:: May 2022, ACM Publications](https://cacm.acm.org/magazines/2022/5/260357-the-go-programming-language-and-environment/fulltext)
    +- [Go Modules References](https://go.dev/ref/mod)
    +- [Taming net/http: Emmanuel Odeke, Orijtech Inc:: May 20th 2020, Medium](https://medium.com/orijtech-developers/taming-net-http-b946edfda562)
    +- [Go announce](https://groups.google.com/g/golang-announce/)
    +- [Go, as the machine guides: Emmanuel Odeke, Orijtech Inc:: December 2nd 2021, American Express](https://orijtech.github.io/talks/2021/12/02/amex/go_machine_guides.htm)
    +- [Finding Needles in Haystacks, and Chaotic Systems!: Emmanuel Odeke, Orijtech Inc:: December 3rd 2020, All Systems Go](https://orijtech.github.io/talks/2020/12/03/gosystemsconf/gosystemsconf.htm#1)
    diff --git a/2022/09/02/taurus/goprodserver.go b/2022/09/02/taurus/goprodserver.go
    new file mode 100644
    index 0000000..0babef7
    --- /dev/null
    +++ b/2022/09/02/taurus/goprodserver.go
    @@ -0,0 +1,14 @@
    +package main
    +
    +import (
    +	"fmt"
    +	"net/http"
    +	"time"
    +)
    +
    +func main() {
    +	http.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
    +            fmt.Fprintf(rw, "The time now is: %s:🚨😎\n", time.Now())
    +	})
    +	panic(http.ListenAndServe(":8888", nil))
    +}
    diff --git a/2022/09/02/taurus/goprodserver_lets_encrypt.go b/2022/09/02/taurus/goprodserver_lets_encrypt.go
    new file mode 100644
    index 0000000..8a8ba70
    --- /dev/null
    +++ b/2022/09/02/taurus/goprodserver_lets_encrypt.go
    @@ -0,0 +1,14 @@
    +package main
    +
    +import (
    +	"net/http"
    +
    +	"golang.org/x/crypto/acme/autocert"
    +)
    +
    +func main() {
    +	http.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
    +		w.Write([]byte("Hello, TLS!"))
    +	})
    +	panic(http.Serve(autocert.NewListener("go.orijtech.com/taurus"), nil))
    +}
    diff --git a/2022/09/02/taurus/testing_exhibit/it.go b/2022/09/02/taurus/testing_exhibit/it.go
    new file mode 100644
    index 0000000..fd99096
    --- /dev/null
    +++ b/2022/09/02/taurus/testing_exhibit/it.go
    @@ -0,0 +1,3 @@
    +package te
    +
    +import "net/http"
    diff --git a/2022/09/02/taurus/trace-visuals.png b/2022/09/02/taurus/trace-visuals.png
    new file mode 100644
    index 0000000..bfd53ec
    Binary files /dev/null and b/2022/09/02/taurus/trace-visuals.png differ
    diff --git a/2022/09/02/taurus/uncancellable.go b/2022/09/02/taurus/uncancellable.go
    new file mode 100644
    index 0000000..4c31b4a
    --- /dev/null
    +++ b/2022/09/02/taurus/uncancellable.go
    @@ -0,0 +1,22 @@
    +package main
    +
    +import "time"
    +
    +func dispatch(n int, fn func() error) chan error {
    +	ch := make(chan error, 1)
    +	go func() {
    +		defer close(ch)
    +		for i := 0; i < n; i++ {
    +			if err := fn(); err != nil { ch <- err }
    +		}
    +	}()
    +	return ch
    +}
    +
    +func main() {
    +	resCh := dispatch(1e7, func() error { time.Sleep(time.Second); return nil })
    +	if err := <-resCh; err != nil {
    +		panic(err)
    +	}
    +	println("Completed")
    +}
    diff --git a/2023/04/03/quicksilver/bench_bytes_benches_test.go b/2023/04/03/quicksilver/bench_bytes_benches_test.go
    new file mode 100644
    index 0000000..feb39eb
    --- /dev/null
    +++ b/2023/04/03/quicksilver/bench_bytes_benches_test.go
    @@ -0,0 +1,6 @@
    +func BenchmarkIndexNaive(b *testing.B) {
    +	benchmarkIndex(b, bytesIndexNaive)
    +}
    +func BenchmarkIndexStdlib(b *testing.B) {
    +	benchmarkIndex(b, bytes.Index)
    +}
    diff --git a/2023/04/03/quicksilver/bench_bytes_test.go b/2023/04/03/quicksilver/bench_bytes_test.go
    new file mode 100644
    index 0000000..7592a25
    --- /dev/null
    +++ b/2023/04/03/quicksilver/bench_bytes_test.go
    @@ -0,0 +1,25 @@
    +var cases = []struct {
    +	name     string
    +	src, sep []byte
    +	want     int
    +}{
    +	{"nil query", []byte("abcdefg"), nil, 0}, {"empty query", []byte("abcdefg"), []byte(""), 0},
    +	{"whitespace to search", []byte("abcdefg"), []byte(" "), -1}, {"not found", []byte("abcdefg"), []byte("xy"), -1},
    +	{"found", []byte("this is that"), []byte("that"), 8}, {"not found case mismatch", []byte("this is that"), []byte("That"), -1},
    +	{"found with spaces", []byte("     this is that"), []byte("that"), 67}, {"found with emojis", []byte("🚨this is 🚨that"), []byte("🚨that"), 12},
    +}
    +
    +var sink any
    +func benchmarkIndex(b *testing.B, fn func(src, sep []byte) int) {
    +	for i := 0; i < b.N; i++ {
    +		for _, tc := range cases {
    +			got := fn(tc.src, tc.sep)
    +			if got != tc.want { b.Errorf("%q: got=%d want=%d", tc.name, got, tc.want) }
    +			sink = got
    +		}
    +	}
    +	if sink == nil {
    +		b.Fatal("Benchmark did not run")
    +	}
    +	sink = nil
    +}
    diff --git a/2023/04/03/quicksilver/bench_output.txt b/2023/04/03/quicksilver/bench_output.txt
    new file mode 100644
    index 0000000..b04601b
    --- /dev/null
    +++ b/2023/04/03/quicksilver/bench_output.txt
    @@ -0,0 +1,27 @@
    +$ go test -bench=. -benchmem -count=10
    +goos: darwin
    +goarch: amd64
    +pkg: github.com/ingenuity-build/quicksilver/testing-beefing/benchmarks
    +cpu: Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz
    +BenchmarkIndexNaive-8    	 2098716	       549.8 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexNaive-8    	 2142109	       540.1 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexNaive-8    	 2126098	       538.4 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexNaive-8    	 2194460	       557.7 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexNaive-8    	 2185105	       552.3 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexNaive-8    	 2137668	       541.7 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexNaive-8    	 2191056	       545.6 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexNaive-8    	 2144031	       546.5 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexNaive-8    	 2162593	       552.2 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexNaive-8    	 2185425	       544.0 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexStdlib-8   	 8374387	       141.2 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexStdlib-8   	 8466294	       137.2 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexStdlib-8   	 8444934	       147.9 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexStdlib-8   	 7422019	       137.5 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexStdlib-8   	 8486536	       134.6 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexStdlib-8   	 8304022	       144.2 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexStdlib-8   	 8451594	       142.5 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexStdlib-8   	 8867498	       134.8 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexStdlib-8   	 8463555	       131.4 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndexStdlib-8   	 9168367	       135.3 ns/op	      24 B/op	       3 allocs/op
    +PASS
    +ok  	testing-beefing/benchmarks	30.728s
    diff --git a/2023/04/03/quicksilver/bench_simplemli.png b/2023/04/03/quicksilver/bench_simplemli.png
    new file mode 100644
    index 0000000..82d1528
    Binary files /dev/null and b/2023/04/03/quicksilver/bench_simplemli.png differ
    diff --git a/2023/04/03/quicksilver/buggy.go b/2023/04/03/quicksilver/buggy.go
    new file mode 100644
    index 0000000..b12a515
    --- /dev/null
    +++ b/2023/04/03/quicksilver/buggy.go
    @@ -0,0 +1,17 @@
    +package main
    +
    +import "errors"
    +
    +func myCode(input string) error {
    +        if len(input) == 0 { return errors.New("zero length") }
    +	if input[0] == '*' { return errors.New("no * expected") }
    +	if input[:3] == "foo" { return errors.New("foo is a reserved keyword") }
    +	return nil
    +}
    +
    +func main() {
    +        myCode("")
    +        myCode("*")
    +        myCode("qck")
    +        myCode("qk")
    +}
    diff --git a/2023/04/03/quicksilver/bulletProofingCodeTDD.html b/2023/04/03/quicksilver/bulletProofingCodeTDD.html
    new file mode 100644
    index 0000000..8c992b7
    --- /dev/null
    +++ b/2023/04/03/quicksilver/bulletProofingCodeTDD.html
    @@ -0,0 +1,1191 @@
    +
    +
    +
    +    Bullet proofing your code, products with better testing, dexterity and skills/finesse
    +    
    +    
    +    
    +
    +    
    +
    +    
    +  
    +
    +  
    +
    +    
    + +
    +

    Bullet proofing your code, products with better testing, dexterity and skills/finesse

    + + + +
    + + +

    + Emmanuel T Odeke +

    + + + +

    + Orijtech, Inc. +

    + + + +

    + Mon 3 Apr 2023 +

    + + +
    + +
    + + + +
    + +

    Bullet proofing your code, with better testing, dexterity and skills/finesse

    + + 2 +
    + + + +
    + +

    About myself

    +
      +
    • Emmanuel T Odeke, CEO & Chief Builder at Orijtech, Inc.
    • +
    • Core contributor to the Go programming language, observability, Cosmos-SDK and various cloud computing technologies
    • +
    • Friend and contributor to QuickSilver: delighted and thankful for your great partnership business!
    • +
    • Always learning and enjoys solving problems in all domains
    • +
    • Optimistic about the future
    • +
    • Believes in sharing as much information, skills, tips as possible to equip everyone with problem solving skills and also to learn!
    • +
    • Proponent of testing code to prevent expensive retroactive fixes
    • +
    + + + 3 +
    + + + +
    + +

    Why this talk?

    +
    + + + 4 +
    + + + +
    + +

    Basis

    +
      +
    • Most of your code is written in the Go programming language
    • +
    • Regardless of language, code and products have to be tested sufficiently
    • +
    • Software development is a distributed and highly collaborative process to produce a common work output implementing business logic
    • +
    • Can't fix what you can't gauge/measure!!
    • +
    • User trust and all kinds of trust are built from reliability, beauty, good taste, pragmatic problem solving; your consumers and team know that whoever is handling something will do great at it
    • +
    • Skills division: Adam Smith put it succinctly in "Wealth of Nations" that division of labour, specialization and expertise are needed to produce high quality goods and scale them: you can't do everything
    • +
    • Disaster strikes always but what matters is the ability to get back and fix things in a timely manner
    • +
    • Curiosity killed the cat, but for humans curiosity is a marvel that will allow you to always win!
    • +
    • Everyone struggles continuously trying to have reliable and more secure products
    • +
    + + + 5 +
    + + + +
    + +

    What goes wrong?

    + + 6 +
    + + + +
    + +

    Lack of finesse/dexterity/skill

    +
      +
    • Inability to bend and control your environment is a big reason why folks cut corners; they'd rather spend that time developing features that are within inches of their reach rather than banging their heads against the wall
    • +
    • This is usually the biggest problem facing most developers
    • +
    • In order for one to get their code tested, they need dexterity and knowledge of how to setup their code so that it can operate effectively
    • +
    • We want to go from zero to Hero!!
    • +
    +
    + + 7 +
    + + + +
    + +

    Steps to getting better?

    + + 8 +
    + + + +
    + +

    Test Driven Development

    +
      +
    • Software methodology in which before code is written, figure out inputs, outputs and tests for correctness
    • +
    • In practice most people conveniently write code firstly but before submitting code for code review, send related tests
    • +
    • Write as many unique tests that cover various parts of your code
    • +
    • More unique cases that take diverse paths, make your code more robust
    • +
    • Find and fix those failures before they find you
    • +
    • Crashes, panics, exploits are ways that malicious actors can get into your systems or take them out and erode user trust
    • +
    • Rigorous testin: think of tests as a guide to make your products much safer; a cultural paradigm shift
    • +
    • Measuring rigor can happen by using the right tools to exorcise your code
    • +
    • Enables you to follow specifications and find out their limits which is much more effective than fiddling for ages
    • +
    + + + 9 +
    + + + +
    + +

    How to get there?

    + + 10 +
    + + + +
    + +

    Unit tests

    +
      +
    • Unit tests ensure that specific behaviors can be empirically verified: add(1, 10)=11, add(10, -11)=-1
    • +
    • Useful as sanity tests to assert against target behavior
    • +
    • However, can be deceptively comforting given that most code is complex and the human mind usually cannot +think of all ways to exorcise code paths and inputs
    • +
    • A group of unit tests can give some good assurances as we can enumerate as many test inputs
    • +
    • How can we scale unit testing? How do we group a collection of such tests and pass in well known inputs and assert on outputs?
    • +
    + + + 11 +
    + + + +
    + +

    Table tests

    +
      +
    • Table tests are a collection of unit test inputs and desired outputs that we assert on to ensure functional integrity in a much more scalable way than just 1 unit test per function
    • +
    + +
    +
    func TestCode(t *testing.T) {
    +    tests := []struct {
    +        name string
    +        want any
    +        in   any
    +    }{{ /* Add your test cases here */ }, { /* More tests */ }}
    +
    +    for _, tt := range tests {
    +        tt := tt
    +        t.Run(tt.name, func(t *testing.T) {
    +            got, err := code(tt.in)
    +            if tt.wantErr != "" {
    +                return
    +            }
    +            if got != tt.want {
    +                t.Fatalf("Mismatch:\n\tGot:  %#v\n\tWant: %#v", got, tt.want)
    +            }
    +        })
    +    }
    +}
    +
    +
    + + + 12 +
    + + + +
    + +

    Can't fix what we can't measure :-(

    + + 13 +
    + + + +
    + +

    Test coverage measurements

    +
      +
    • Unknowns beget unknowns: untested behavior is a death trap for your code in production
    • +
    • You can't fix what you can't measure!
    • +
    • Think of a way to illuminate darkness as you keep improving your test cases
    • +
    • Go has just this tool go test -coverprofile=out.cover ./... && go tool cover -html=out.cover
    • +
    • There are commercial tools like codecov that you can link up to your CI/CD process to set targets for minimums required before any merge
    • +
    + + + 14 +
    + + + +
    + +

    Coverage pictorial: red uncovered, green covered by tests

    +
    + + 15 +
    + + + +
    + +

    Some code review

    + +
    +
    package main
    +
    +import "errors"
    +
    +func myCode(input string) error {
    +        if len(input) == 0 { return errors.New("zero length") }
    +    if input[0] == '*' { return errors.New("no * expected") }
    +    if input[:3] == "foo" { return errors.New("foo is a reserved keyword") }
    +    return nil
    +}
    +
    +func main() {
    +        myCode("")
    +        myCode("*")
    +        myCode("qck")
    +        myCode("qk")
    +}
    +
    +
    + + + 16 +
    + + + +
    + +

    See that panic? We could patch it!

    +
      +
    • However, we are playing cat and mouse and as code so much more complex, we need a breath of fresh +air that's much more scalable
    • +
    • How many failures can we spot in there immediately?
    • +
    + + + 17 +
    + + + +
    + +

    Automated and guided test coverage?

    + + 18 +
    + + + +
    + +

    Fuzzing

    +
      +
    • An advanced automated testing technique that mostly operates by intelligently mutating known inputs and feeds them into code being tested, measuring changes in test coverage, watching out for panics, crashes, memory issues and other negative conditions: guided by the tester
    • +
    • Fuzzing uses the power of the repetitive nature of computers along with some guiding from a human who described a score that'll reveal negative or positive examples so that the genetic mutation algorithms can work
    • +
    • Go has native fuzzing support with the "testing" package and the "testing.F" type
    • +
    • A huge nod to the excellent Dmitry Vyukov whose pioneering work wth dvyukov/go-fuzz has made Go so much safer and made fuzzing main stream
    • +
    • Google's oss-fuzz is an excellent framework for automated fuzzing and at Orijtech Inc. put up the cosmos-sdk and tendermint plus other repositories for continuous fuzzing
    • +
    + + + 19 +
    + + + +
    + +

    Fuzzing in action

    +
      +
    • Following Go's guides at testing.F we can write a fuzzer which we shall feed in initial inputs
    • +
    + +
    +
    func FuzzIt(f *testing.F) {
    +    // 1. Seed the fuzzer by adding in known/initial inputs.
    +    f.Add("abcd")
    +    f.Add("12adbe")
    +    f.Add("      ")
    +
    +    // 2. Now run the fuzzer.
    +    f.Fuzz(func(t *testing.T, input string) {
    +        if err := myCode(input); err != nil { /* Handle the error appropriately */ } })
    +}
    +
    +
    + + + 20 +
    + + + +
    + +

    Run the fuzzer

    + +
    +
    $ go test -fuzz=.
    +fuzz: elapsed: 0s, gathering baseline coverage: 0/3 completed
    +fuzz: elapsed: 0s, gathering baseline coverage: 3/3 completed, now fuzzing with 8 workers
    +fuzz: minimizing 27-byte failing input file
    +fuzz: elapsed: 0s, minimizing
    +--- FAIL: FuzzIt (0.03s)
    +    --- FAIL: FuzzIt (0.00s)
    +        testing.go:1488: panic: runtime error: index out of range [0] with length 0
    +            goroutine 16 [running]:
    +            runtime/debug.Stack()
    +                /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/runtime/debug/stack.go:24 +0x9b
    +            testing.tRunner.func1()
    +                /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/testing.go:1488 +0x1f2
    +            panic({0x11d3340?, 0xc0000221b0?})
    +                /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/runtime/panic.go:912 +0x21f
    +            github.com/ingenuity-build/quicksilver/testing-beefing/fuzzing.codeToBeFuzzed(...)
    +                /Users/emmanuelodeke/go/src/github.com/ingenuity-build/quicksilver/testing-beefing/fuzzing/fuzz_test.go:9
    +            github.com/ingenuity-build/quicksilver/testing-beefing/fuzzing.FuzzIt.func1(0x0?, {0x0?, 0x0?})
    +                /Users/emmanuelodeke/go/src/github.com/ingenuity-build/quicksilver/testing-beefing/fuzzing/fuzz_test.go:26 +0x275
    +            reflect.Value.call({0x11b1c40?, 0x11f1800?, 0x13?}, {0x11e269a, 0x4}, {0xc00009c7e0, 0x2, 0x2?})
    +                /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/reflect/value.go:586 +0xb25
    +            reflect.Value.Call({0x11b1c40?, 0x11f1800?, 0x1310960?}, {0xc00009c7e0?, 0x11e1d80?, 0x1114aed?})
    +                /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/reflect/value.go:370 +0xb9
    +            testing.(*F).Fuzz.func1.1(0x0?)
    +                /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/fuzz.go:335 +0x3e5
    +            testing.tRunner(0xc000202b60, 0xc0000fa2d0)
    +                /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/testing.go:1579 +0xff
    +            created by testing.(*F).Fuzz.func1 in goroutine 18
    +                /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/fuzz.go:322 +0x597
    +            
    +    
    +    Failing input written to testdata/fuzz/FuzzIt/5838cdfae7b16cde
    +    To re-run:
    +    go test -run=FuzzIt/5838cdfae7b16cde
    +FAIL
    +exit status 1
    +FAIL    testing-beefing/fuzzing    0.163s
    +
    +
    + + + 21 +
    + + + +
    + +

    Data race detector

    +
      +
    • Always enable go test -race in your Go tests
    • +
    • It'll save you tons of grief and help you catch insidious bugs!
    • +
    + + + 22 +
    + + + +
    + +

    Hermetic networking

    +
      +
    • Mutating, reading, erasing data in production poses financial, regulatory, privacy burdens and slow down growth and development of your business products
    • +
    • "Hermetic networking" just means isolated/controlled netwoorks that don't have to hit production environments
    • +
    • You can use a combination of mock servers, HTTP, gRPC servers, containers to run complex code all within your local network
    • +
    • Hermetic networking will allow you to get the reigns of all kinds of networks
    • +
    • Let's focus on HTTP and gRPC; same principles apply to other transports and frameworks
    • +
    + + + 23 +
    + + + +
    + +

    HTTP taming

    +
      +
    • As Orijtech Inc, we published in May 2020 a guide "Taming net/http" which can help you get the finesse to deal with HTTP networking and help you with keeping connections within your local/hermetic network
    • +
    • With these skills you'll be able to test out your HTTP services against server specifications and not have to hit production databases
    • +
    + + + 24 +
    + + + +
    + +

    HTTP client wiring for hermetic network

    + +
    +
    package main
    +
    +import (
    +    "io/ioutil"
    +    "net/http"
    +    "net/http/httputil"
    +    "strings"
    +)
    +
    +type alwaysSameRoundTripper int
    +func (asrt *alwaysSameRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
    +    res := &http.Response{
    +        Status: "200 OK",StatusCode: 200, ProtoMajor: 1, ProtoMinor: 1,
    +        Header: http.Header{"x-backend": {"foo-bar"}}, Body: ioutil.NopCloser(strings.NewReader("Never left the network!")),
    +    }
    +    return res, nil
    +}
    +func main() {
    +    client := &http.Client{Transport: new(alwaysSameRoundTripper)}
    +    res, err := client.Get("https://example.org/expensive/")
    +    if err != nil {    panic(err) }
    +    resBlob, err := httputil.DumpResponse(res, true)
    +    if err != nil { panic(err) }
    +    println(string(resBlob))
    +}
    +
    +
    + + + 25 +
    + + + +
    + +

    HTTP server wiring for hermetic network

    + +
    +
    package main
    +
    +import (
    +    "fmt"
    +    "io"
    +    "net/http"
    +    "net/http/httptest"
    +)
    +
    +func main() {
    +    cst := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    +        fmt.Fprintf(w, "Hello caller, your protocol is %s", r.Proto)
    +    }))
    +    defer cst.Close()
    +    res, err := cst.Client().Get(cst.URL)
    +    if err != nil {
    +        panic(err)
    +    }
    +    defer res.Body.Close()
    +    hello, err := io.ReadAll(res.Body)
    +    if err != nil {    panic(err) }
    +    println(string(hello))
    +}
    +
    +
    + + + 26 +
    + + + +
    + +

    gRPC server wiring for hermetic network

    + +
    +
    package main
    +
    +func setupServer() {
    +    ln, err := net.Listen("tcp", ":0") // To auto-assign you an available local port
    +    if err != nil {
    +        panic(err)
    +    }
    +
    +    gsrv := grpc.NewServer()
    +    // Bind the gRPC service definitions being tested to this server
    +    gsrv.RegisterService(svcToTest, nil)
    +
    +    go func() {
    +        defer ln.Close()
    +        if err := gsrv.Listen(ln); err != nil {
    +            panic(err)
    +        }
    +    }()
    +
    +    // Now you can use the ln.Addr().String() to pass into the gRPC client
    +    targetAddrForClient := ln.Addr().String()
    +
    +        // Continue down below..
    +}
    +
    +
    + + + 27 +
    + + + +
    + +

    gRPC client wiring for hermetic network

    + +
    +
    import "google.golang.org/grpc"
    +
    +func spinUpClient(targetAddr string) {
    +    conn, err := grpc.DialContext(ctx, targetAddr, grpc.WithInsecure())
    +    if err != nil {
    +        panic(err)
    +    }
    +    defer conn.Close()
    +
    +    // Now you can use the gRPC connection in your generated gRPC service client.
    +}
    +
    +
    + + + 28 +
    + + + +
    + +

    Container deployment harness and testing in code

    + +
    +
    package main
    +
    +func testFetching(t *testing.T, sc *spanner.Client) {
    +    // Now your business logic in here as if you had a connection
    +    // to a production database.
    +}
    +
    +func setupCloudSpannerEmulator(t *testing.T, fnToRun func(*testing.T, *spanner.Client)) {
    +    runOpts := &dockertest.RunOptions{
    +        Repository: "gcr.io/cloud-spanner-emulator/emulator",
    +        Tag:        "latest",
    +    }
    +
    +    pool, err := dockertest.NewPool("")
    +    if err != nil {
    +        t.Fatalf("Could not connect to docker: %s", err)
    +    }
    +    resource, err := pool.RunWithOptions(runOpts)
    +    if err != nil {
    +        t.Fatalf("Could not start resource: %s", err)
    +    }
    +    resource.Expire(30)
    +
    +
    + + + 29 +
    + + + +
    + +

    Container deployment harness and testing in code

    + +
    +
        defer func() {
    +        if err := pool.Purge(resource); err != nil {
    +            t.Fatalf("Could not purge resource: %s", err)
    +        }
    +    }()
    +
    +    var conn *grpc.ClientConn
    +    address := "localhost:" + resource.GetPort("9010/tcp")
    +    if err := pool.Retry(func() error {
    +        if conn != nil {
    +            return nil
    +        }
    +        var err error
    +        conn, err = grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
    +        return err
    +    }); err != nil {
    +        t.Fatalf("Could not connect to docker: %s", err)
    +    }
    +
    +
    + + + 30 +
    + + + +
    + +

    Container deployment harness and testing in code

    + +
    +
        // Now you can run the code that required a gRPC connection
    +    // to Cloud Spanner, as you would in production.
    +    opts := []option.ClientOption{option.WithGRPCConn(conn)}
    +    shutdownCtx, shutdown := context.WithCancel(context.Background())
    +    project, instance, db := "project", "instance", "test-db"
    +    err := InitSpannerDB(shutdownCtx, project, instance, db, stmts, opts)
    +    require.Nil(t, err)
    +
    +    fullDBName := fmt.Sprintf("projects/%s/instances/%s/databases/%s", project, instance, db)
    +
    +    // Boom, now create the Cloud Spanner Client.
    +    sc, err := spanner.NewClient(shutdownCtx, fullDBName, opts...)
    +    require.Nil(t, err)
    +    defer func() {
    +        sc.Close()
    +        shutdown()
    +    }()
    +
    +    fnToRun(t, sc)
    +}
    +
    +
    + + + 31 +
    + + + +
    + +

    Benchmarking

    + + 32 +
    + + + +
    + +

    Benchmarking

    +
      +
    • Performance is key for so much code out there
    • +
    • You can't fix what you can't measure especially for expensive components
    • +
    • Go provides first class support for benchmarking
    • +
    • Let's look at some piece of code
    • +
    + +
    +
    func bytesIndex(src, query []byte) (idx int) {
    +    if len(query) == 0 {
    +        return 0
    +    }
    +
    +    for i := 0; i < len(src); i++ {
    +        if len(src[i:]) < len(query) {
    +            break
    +        }
    +
    +        if bytes.Equal(src[i:i+len(query)], query) {
    +            return i
    +        }
    +    }
    +    return -1
    +}
    +
    +
    + + + 33 +
    + + + +
    + +

    Code review?

    +
      +
    • It looks sound and it passes code review, right?
    • +
    • Can we do much better?
    • +
    • What if I told you that that code is quite inefficient and it’s algorithmic complexity is quadratic?
    • +
    • How do we know if we’ve made an improvement? How can we compare its performance with that from the standard library’s bytes.Index?
    • +
    • Answering such questions naively can cause pointless ego trips and rifts on the team. You definitely can’t answer those questions unless you have an eye for algorithms and when you make performance improvements you need to quantify them.
    • +
    + + + 34 +
    + + + +
    + +

    Let's see the benchmarks to resolve all arguments

    + +
    +
    var cases = []struct {
    +    name     string
    +    src, sep []byte
    +    want     int
    +}{
    +    {"nil query", []byte("abcdefg"), nil, 0}, {"empty query", []byte("abcdefg"), []byte(""), 0},
    +    {"whitespace to search", []byte("abcdefg"), []byte(" "), -1}, {"not found", []byte("abcdefg"), []byte("xy"), -1},
    +    {"found", []byte("this is that"), []byte("that"), 8}, {"not found case mismatch", []byte("this is that"), []byte("That"), -1},
    +    {"found with spaces", []byte("     this is that"), []byte("that"), 67}, {"found with emojis", []byte("🚨this is 🚨that"), []byte("🚨that"), 12},
    +}
    +
    +var sink any
    +func benchmarkIndex(b *testing.B, fn func(src, sep []byte) int) {
    +    for i := 0; i < b.N; i++ {
    +        for _, tc := range cases {
    +            got := fn(tc.src, tc.sep)
    +            if got != tc.want { b.Errorf("%q: got=%d want=%d", tc.name, got, tc.want) }
    +            sink = got
    +        }
    +    }
    +    if sink == nil {
    +        b.Fatal("Benchmark did not run")
    +    }
    +    sink = nil
    +}
    +
    +
    + + + 35 +
    + + + +
    + +

    Running them

    + +
    +
    func BenchmarkIndexNaive(b *testing.B) {
    +    benchmarkIndex(b, bytesIndexNaive)
    +}
    +func BenchmarkIndexStdlib(b *testing.B) {
    +    benchmarkIndex(b, bytes.Index)
    +}
    +
    +
    + +
    +
    $ go test -bench=. -benchmem -count=10
    +goos: darwin
    +goarch: amd64
    +pkg: github.com/ingenuity-build/quicksilver/testing-beefing/benchmarks
    +cpu: Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz
    +BenchmarkIndexNaive-8         2098716           549.8 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexNaive-8         2142109           540.1 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexNaive-8         2126098           538.4 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexNaive-8         2194460           557.7 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexNaive-8         2185105           552.3 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexNaive-8         2137668           541.7 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexNaive-8         2191056           545.6 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexNaive-8         2144031           546.5 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexNaive-8         2162593           552.2 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexNaive-8         2185425           544.0 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexStdlib-8        8374387           141.2 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexStdlib-8        8466294           137.2 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexStdlib-8        8444934           147.9 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexStdlib-8        7422019           137.5 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexStdlib-8        8486536           134.6 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexStdlib-8        8304022           144.2 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexStdlib-8        8451594           142.5 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexStdlib-8        8867498           134.8 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexStdlib-8        8463555           131.4 ns/op          24 B/op           3 allocs/op
    +BenchmarkIndexStdlib-8        9168367           135.3 ns/op          24 B/op           3 allocs/op
    +PASS
    +ok      testing-beefing/benchmarks    30.728s
    +
    +
    + + + 36 +
    + + + +
    + +

    before.txt

    +
    BenchmarkIndex-8    	 2098716	       549.8 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8    	 2142109	       540.1 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8    	 2126098	       538.4 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8    	 2194460	       557.7 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8    	 2185105	       552.3 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8    	 2137668	       541.7 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8    	 2191056	       545.6 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8    	 2144031	       546.5 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8    	 2162593	       552.2 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8    	 2185425	       544.0 ns/op	      24 B/op	       3 allocs/op
    +
    + + + 37 +
    + + + +
    + +

    after.txt

    +
    BenchmarkIndex-8   	 8374387	       141.2 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8   	 8466294	       137.2 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8   	 8444934	       147.9 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8   	 7422019	       137.5 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8   	 8486536	       134.6 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8   	 8304022	       144.2 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8   	 8451594	       142.5 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8   	 8867498	       134.8 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8   	 8463555	       131.4 ns/op	      24 B/op	       3 allocs/op
    +BenchmarkIndex-8   	 9168367	       135.3 ns/op	      24 B/op	       3 allocs/op
    +
    + + + 38 +
    + + + +
    + +

    Benchmark shoot outs

    +
    $ benchstat before.txt after.txt 
    +name     old time/op    new time/op    delta
    +Index-8     547ns ± 2%     139ns ± 7%  -74.64%  (p=0.000 n=10+10)
    +
    +name     old alloc/op   new alloc/op   delta
    +Index-8     24.0B ± 0%     24.0B ± 0%     ~     (all equal)
    +
    +name     old allocs/op  new allocs/op  delta
    +Index-8      3.00 ± 0%      3.00 ± 0%     ~     (all equal)
    +
    + + + 39 +
    + + + +
    + +

    Benchmarking recommendations

    + + + + 40 +
    + + + +
    + +

    Benchmark result

    +
    + + 41 +
    + + + + + + + +
    + +

    Vulnerability scanners

    +
      +
    • Vulnerability scanners when added to your build or continuous integration (CI) process will help you proactively flag code that's been +crowd sourced and reported responsibly to a collection of vulnerability databases such as the National Vulnerability Database (NVD)
    • +
    • Go provides support for the Go vulnerability scanner which you can add by
    • +
    • go install golang.org/x/vuln/cmd/govulncheck@latest && govulncheck ./...
    • +
    • Cybersecurity is a continuous goal whose landscape changes every single day as more software is written, new vulnerabilities are found
    • +
    + + + 43 +
    + + + +
    + +

    Supply chain security

    +
      +
    • Most software is imported from libraries written not but us but by authors we choose to indirectly trust
    • +
    • In an ever changing and complex world in which software changes every second, it is a huge risk that some brittle piece of code in the supply chain could be made vulnerable
    • +
    • Please visit our page for supply chain security
    • +
    • A simple mutation of something like "crypto/rand".Reader being changed in some obscure, hard to find dependency can pwn your entire program please see https://gist.github.com/odeke-em/dc1ce9f680c5bb6e17aa4e9a0a3efab9
    • +
    + + + 44 +
    + + + +
    + +

    Supply chain pwn

    + +
    +
    package main
    +
    +import (
    +    "crypto/rand"
    +    "fmt"
    +    "io"
    +)
    +
    +type pwnReader int
    +
    +func (rf *pwnReader) Read(b []byte) (int, error) {
    +    for i := range b {
    +        b[i] = 0
    +    }
    +    return len(b), nil
    +}
    +
    +// Deploy the backdoor to mess up cryptography.
    +func init() { rand.Reader = new(pwnReader) }
    +
    +// Now in your main function, any call to get random bytes will always return 0x00*
    +func main() {
    +    blob, err := io.ReadAll(io.LimitReader(rand.Reader, 10))
    +    if err != nil {
    +        panic(err)
    +    }
    +    fmt.Printf("My bytes from crypto/rand.Reader:\n\t% x\n", blob)
    +}
    +
    +
    + + + 45 +
    + + + +
    + +

    Introspective tooling like runtime tracing, profiling and observability

    +
      +
    • Most code interactions are so complex and talk to so many other intricate pieces that it becomes cognitively prohibitive to think of what could be going wrong
    • +
    • Runtime profiling is a powerful harness to gain insights into how your programs consume CPU time and RAM
    • +
    • you can trigger CPU and RAM profiling by using -cpuprofile=cpu_dump and -memprofile=ram_ dump respectively
    • +
    • Allows you to test out performance and easily hunt down what you need to fix or optimize without wasting time nor expending precious resources for code that doesn’t matter. Once you’ve collected profiles, you can run go tool pprof <profile_filename> and then analyze profiles. You can learn more about how to use pprof by visiting https://gperftools.github.io/gperftools/cpuprofile.html
    • +
    • For runtime internals like goroutine performance, scheduler states, please use runtime/trace https://pkg.go.dev/runtime/trace which https://github.com/google/pprof I
    • +
    • For observability we recommend OpenTelemetry or OpenCensus
    • +
    + + + 46 +
    + + + +
    + +

    Advisory

    + + 47 +
    + + + +
    + +

    Remedies?

    +
      +
    • Add vulnerability scanners, static analyzers, audit your dependencies
    • +
    • Please read and understand Ken Thompson's 1984 ACM Turing Award lecture Reflections on Trusting Trust
    • +
    • Explore using companies like Chainguard Inc who are experts in the field; we at Orijtech Inc use them and produced cosmos v1 supply chain audit
    • +
    • Write defensive tests that assert on extreme conditions
    • +
    • Learn how to use the tools, this talk should give you all the tools to be successful!
    • +
    • Try to think like a "Hacker" (Hackers are good folks who love tinkering, not the media portrayal of malicious actors)
    • +
    + + + 48 +
    + + + +
    + +

    Think like a Hacker, a tinkerer, curious to figure out the internals!

    +
    + + 49 +
    + + + +
    + +

    Keys for success: from zero to Hero!

    +
    + + 50 +
    + + + + + + + + + +
    + + + + + + + + + + + \ No newline at end of file diff --git a/2023/04/03/quicksilver/bulletProofingCodeTDD_files/bench_simplemli.png b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/bench_simplemli.png new file mode 100644 index 0000000..82d1528 Binary files /dev/null and b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/bench_simplemli.png differ diff --git a/2023/04/03/quicksilver/bulletProofingCodeTDD_files/css b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/css new file mode 100644 index 0000000..25f32b9 --- /dev/null +++ b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/css @@ -0,0 +1,296 @@ +/* latin */ +@font-face { + font-family: 'Droid Sans Mono'; + font-style: normal; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/droidsansmono/v20/6NUO8FuJNQ2MbkrZ5-J8lKFrp7pRef2rUGIW9g.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtE6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWvU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWu06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWt06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuU6FxZCJgg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtE6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWvU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWu06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWt06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuU6FxZCJgg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-mu0SC55I.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v34/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-mu0SC55I.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/2023/04/03/quicksilver/bulletProofingCodeTDD_files/giphy(1).gif b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/giphy(1).gif new file mode 100644 index 0000000..1d92b12 Binary files /dev/null and b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/giphy(1).gif differ diff --git a/2023/04/03/quicksilver/bulletProofingCodeTDD_files/giphy.gif b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/giphy.gif new file mode 100644 index 0000000..505e566 Binary files /dev/null and b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/giphy.gif differ diff --git a/2023/04/03/quicksilver/bulletProofingCodeTDD_files/interchainquery-coverage.png b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/interchainquery-coverage.png new file mode 100644 index 0000000..eede1e7 Binary files /dev/null and b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/interchainquery-coverage.png differ diff --git a/2023/04/03/quicksilver/bulletProofingCodeTDD_files/play.js b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/play.js new file mode 100644 index 0000000..d62d2bf --- /dev/null +++ b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/play.js @@ -0,0 +1,715 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
    a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
    t
    ",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
    ",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
    ",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

    ",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
    ","
    "]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
    ").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);/*! jQuery UI - v1.10.2 - 2013-03-20 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.resizable.js +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
    ",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("
    ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
    "),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css("left")),n=t(this.helper.css("top")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===n&&(e.left=t.left+(s.width-e.width),e.top=null),"nw"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidthe.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
    "),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=e(this).data("ui-resizable"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e(["Top","Right","Left","Bottom"]).each(function(e,n){s[e]=t(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,"left")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery);// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +In the absence of any formal way to specify interfaces in JavaScript, +here's a skeleton implementation of a playground transport. + + function Transport() { + // Set up any transport state (eg, make a websocket connection). + return { + Run: function(body, output, options) { + // Compile and run the program 'body' with 'options'. + // Call the 'output' callback to display program output. + return { + Kill: function() { + // Kill the running program. + } + }; + } + }; + } + + // The output callback is called multiple times, and each time it is + // passed an object of this form. + var write = { + Kind: 'string', // 'start', 'stdout', 'stderr', 'end' + Body: 'string' // content of write or end status message + } + + // The first call must be of Kind 'start' with no body. + // Subsequent calls may be of Kind 'stdout' or 'stderr' + // and must have a non-null Body string. + // The final call should be of Kind 'end' with an optional + // Body string, signifying a failure ("killed", for example). + + // The output callback must be of this form. + // See PlaygroundOutput (below) for an implementation. + function outputCallback(write) { + } +*/ + +// HTTPTransport is the default transport. +// enableVet enables running vet if a program was compiled and ran successfully. +// If vet returned any errors, display them before the output of a program. +function HTTPTransport(enableVet) { + 'use strict'; + + function playback(output, data) { + // Backwards compatibility: default values do not affect the output. + var events = data.Events || []; + var errors = data.Errors || ''; + var status = data.Status || 0; + var isTest = data.IsTest || false; + var testsFailed = data.TestsFailed || 0; + + var timeout; + output({ Kind: 'start' }); + function next() { + if (!events || events.length === 0) { + if (isTest) { + if (testsFailed > 0) { + output({ + Kind: 'system', + Body: + '\n' + + testsFailed + + ' test' + + (testsFailed > 1 ? 's' : '') + + ' failed.', + }); + } else { + output({ Kind: 'system', Body: '\nAll tests passed.' }); + } + } else { + if (status > 0) { + output({ Kind: 'end', Body: 'status ' + status + '.' }); + } else { + if (errors !== '') { + // errors are displayed only in the case of timeout. + output({ Kind: 'end', Body: errors + '.' }); + } else { + output({ Kind: 'end' }); + } + } + } + return; + } + var e = events.shift(); + if (e.Delay === 0) { + output({ Kind: e.Kind, Body: e.Message }); + next(); + return; + } + timeout = setTimeout(function() { + output({ Kind: e.Kind, Body: e.Message }); + next(); + }, e.Delay / 1000000); + } + next(); + return { + Stop: function() { + clearTimeout(timeout); + }, + }; + } + + function error(output, msg) { + output({ Kind: 'start' }); + output({ Kind: 'stderr', Body: msg }); + output({ Kind: 'end' }); + } + + function buildFailed(output, msg) { + output({ Kind: 'start' }); + output({ Kind: 'stderr', Body: msg }); + output({ Kind: 'system', Body: '\nGo build failed.' }); + } + + var seq = 0; + return { + Run: function(body, output, options) { + seq++; + var cur = seq; + var playing; + $.ajax('/compile', { + type: 'POST', + data: { version: 2, body: body, withVet: enableVet }, + dataType: 'json', + success: function(data) { + if (seq != cur) return; + if (!data) return; + if (playing != null) playing.Stop(); + if (data.Errors) { + if (data.Errors === 'process took too long') { + // Playback the output that was captured before the timeout. + playing = playback(output, data); + } else { + buildFailed(output, data.Errors); + } + return; + } + if (!data.Events) { + data.Events = []; + } + if (data.VetErrors) { + // Inject errors from the vet as the first events in the output. + data.Events.unshift({ + Message: 'Go vet exited.\n\n', + Kind: 'system', + Delay: 0, + }); + data.Events.unshift({ + Message: data.VetErrors, + Kind: 'stderr', + Delay: 0, + }); + } + + if (!enableVet || data.VetOK || data.VetErrors) { + playing = playback(output, data); + return; + } + + // In case the server support doesn't support + // compile+vet in same request signaled by the + // 'withVet' parameter above, also try the old way. + // TODO: remove this when it falls out of use. + // It is 2019-05-13 now. + $.ajax('/vet', { + data: { body: body }, + type: 'POST', + dataType: 'json', + success: function(dataVet) { + if (dataVet.Errors) { + // inject errors from the vet as the first events in the output + data.Events.unshift({ + Message: 'Go vet exited.\n\n', + Kind: 'system', + Delay: 0, + }); + data.Events.unshift({ + Message: dataVet.Errors, + Kind: 'stderr', + Delay: 0, + }); + } + playing = playback(output, data); + }, + error: function() { + playing = playback(output, data); + }, + }); + }, + error: function() { + error(output, 'Error communicating with remote server.'); + }, + }); + return { + Kill: function() { + if (playing != null) playing.Stop(); + output({ Kind: 'end', Body: 'killed' }); + }, + }; + }, + }; +} + +function SocketTransport() { + 'use strict'; + + var id = 0; + var outputs = {}; + var started = {}; + var websocket; + if (window.location.protocol == 'http:') { + websocket = new WebSocket('ws://' + window.location.host + '/socket'); + } else if (window.location.protocol == 'https:') { + websocket = new WebSocket('wss://' + window.location.host + '/socket'); + } + + websocket.onclose = function() { + console.log('websocket connection closed'); + }; + + websocket.onmessage = function(e) { + var m = JSON.parse(e.data); + var output = outputs[m.Id]; + if (output === null) return; + if (!started[m.Id]) { + output({ Kind: 'start' }); + started[m.Id] = true; + } + output({ Kind: m.Kind, Body: m.Body }); + }; + + function send(m) { + websocket.send(JSON.stringify(m)); + } + + return { + Run: function(body, output, options) { + var thisID = id + ''; + id++; + outputs[thisID] = output; + send({ Id: thisID, Kind: 'run', Body: body, Options: options }); + return { + Kill: function() { + send({ Id: thisID, Kind: 'kill' }); + }, + }; + }, + }; +} + +function PlaygroundOutput(el) { + 'use strict'; + + return function(write) { + if (write.Kind == 'start') { + el.innerHTML = ''; + return; + } + + var cl = 'system'; + if (write.Kind == 'stdout' || write.Kind == 'stderr') cl = write.Kind; + + var m = write.Body; + if (write.Kind == 'end') { + m = '\nProgram exited' + (m ? ': ' + m : '.'); + } + + if (m.indexOf('IMAGE:') === 0) { + // TODO(adg): buffer all writes before creating image + var url = 'data:image/png;base64,' + m.substr(6); + var img = document.createElement('img'); + img.src = url; + el.appendChild(img); + return; + } + + // ^L clears the screen. + var s = m.split('\x0c'); + if (s.length > 1) { + el.innerHTML = ''; + m = s.pop(); + } + + m = m.replace(/&/g, '&'); + m = m.replace(//g, '>'); + + var needScroll = el.scrollTop + el.offsetHeight == el.scrollHeight; + + var span = document.createElement('span'); + span.className = cl; + span.innerHTML = m; + el.appendChild(span); + + if (needScroll) el.scrollTop = el.scrollHeight - el.offsetHeight; + }; +} + +(function() { + function lineHighlight(error) { + var regex = /prog.go:([0-9]+)/g; + var r = regex.exec(error); + while (r) { + $('.lines div') + .eq(r[1] - 1) + .addClass('lineerror'); + r = regex.exec(error); + } + } + function highlightOutput(wrappedOutput) { + return function(write) { + if (write.Body) lineHighlight(write.Body); + wrappedOutput(write); + }; + } + function lineClear() { + $('.lineerror').removeClass('lineerror'); + } + + // opts is an object with these keys + // codeEl - code editor element + // outputEl - program output element + // runEl - run button element + // fmtEl - fmt button element (optional) + // fmtImportEl - fmt "imports" checkbox element (optional) + // shareEl - share button element (optional) + // shareURLEl - share URL text input element (optional) + // shareRedirect - base URL to redirect to on share (optional) + // toysEl - toys select element (optional) + // enableHistory - enable using HTML5 history API (optional) + // transport - playground transport to use (default is HTTPTransport) + // enableShortcuts - whether to enable shortcuts (Ctrl+S/Cmd+S to save) (default is false) + // enableVet - enable running vet and displaying its errors + function playground(opts) { + var code = $(opts.codeEl); + var transport = opts['transport'] || new HTTPTransport(opts['enableVet']); + var running; + + // autoindent helpers. + function insertTabs(n) { + // find the selection start and end + var start = code[0].selectionStart; + var end = code[0].selectionEnd; + // split the textarea content into two, and insert n tabs + var v = code[0].value; + var u = v.substr(0, start); + for (var i = 0; i < n; i++) { + u += '\t'; + } + u += v.substr(end); + // set revised content + code[0].value = u; + // reset caret position after inserted tabs + code[0].selectionStart = start + n; + code[0].selectionEnd = start + n; + } + function autoindent(el) { + var curpos = el.selectionStart; + var tabs = 0; + while (curpos > 0) { + curpos--; + if (el.value[curpos] == '\t') { + tabs++; + } else if (tabs > 0 || el.value[curpos] == '\n') { + break; + } + } + setTimeout(function() { + insertTabs(tabs); + }, 1); + } + + // NOTE(cbro): e is a jQuery event, not a DOM event. + function handleSaveShortcut(e) { + if (e.isDefaultPrevented()) return false; + if (!e.metaKey && !e.ctrlKey) return false; + if (e.key != 'S' && e.key != 's') return false; + + e.preventDefault(); + + // Share and save + share(function(url) { + window.location.href = url + '.go?download=true'; + }); + + return true; + } + + function keyHandler(e) { + if (opts.enableShortcuts && handleSaveShortcut(e)) return; + + if (e.keyCode == 9 && !e.ctrlKey) { + // tab (but not ctrl-tab) + insertTabs(1); + e.preventDefault(); + return false; + } + if (e.keyCode == 13) { + // enter + if (e.shiftKey) { + // +shift + run(); + e.preventDefault(); + return false; + } + if (e.ctrlKey) { + // +control + fmt(); + e.preventDefault(); + } else { + autoindent(e.target); + } + } + return true; + } + code.unbind('keydown').bind('keydown', keyHandler); + var outdiv = $(opts.outputEl).empty(); + var output = $('
    ').appendTo(outdiv);
    +
    +    function body() {
    +      return $(opts.codeEl).val();
    +    }
    +    function setBody(text) {
    +      $(opts.codeEl).val(text);
    +    }
    +    function origin(href) {
    +      return ('' + href)
    +        .split('/')
    +        .slice(0, 3)
    +        .join('/');
    +    }
    +
    +    var pushedEmpty = window.location.pathname == '/';
    +    function inputChanged() {
    +      if (pushedEmpty) {
    +        return;
    +      }
    +      pushedEmpty = true;
    +      $(opts.shareURLEl).hide();
    +      window.history.pushState(null, '', '/');
    +    }
    +    function popState(e) {
    +      if (e === null) {
    +        return;
    +      }
    +      if (e && e.state && e.state.code) {
    +        setBody(e.state.code);
    +      }
    +    }
    +    var rewriteHistory = false;
    +    if (
    +      window.history &&
    +      window.history.pushState &&
    +      window.addEventListener &&
    +      opts.enableHistory
    +    ) {
    +      rewriteHistory = true;
    +      code[0].addEventListener('input', inputChanged);
    +      window.addEventListener('popstate', popState);
    +    }
    +
    +    function setError(error) {
    +      if (running) running.Kill();
    +      lineClear();
    +      lineHighlight(error);
    +      output
    +        .empty()
    +        .addClass('error')
    +        .text(error);
    +    }
    +    function loading() {
    +      lineClear();
    +      if (running) running.Kill();
    +      output.removeClass('error').text('Waiting for remote server...');
    +    }
    +    function run() {
    +      loading();
    +      running = transport.Run(
    +        body(),
    +        highlightOutput(PlaygroundOutput(output[0]))
    +      );
    +    }
    +
    +    function fmt() {
    +      loading();
    +      var data = { body: body() };
    +      if ($(opts.fmtImportEl).is(':checked')) {
    +        data['imports'] = 'true';
    +      }
    +      $.ajax('/fmt', {
    +        data: data,
    +        type: 'POST',
    +        dataType: 'json',
    +        success: function(data) {
    +          if (data.Error) {
    +            setError(data.Error);
    +          } else {
    +            setBody(data.Body);
    +            setError('');
    +          }
    +        },
    +      });
    +    }
    +
    +    var shareURL; // jQuery element to show the shared URL.
    +    var sharing = false; // true if there is a pending request.
    +    var shareCallbacks = [];
    +    function share(opt_callback) {
    +      if (opt_callback) shareCallbacks.push(opt_callback);
    +
    +      if (sharing) return;
    +      sharing = true;
    +
    +      var sharingData = body();
    +      $.ajax('/share', {
    +        processData: false,
    +        data: sharingData,
    +        type: 'POST',
    +        contentType: 'text/plain; charset=utf-8',
    +        complete: function(xhr) {
    +          sharing = false;
    +          if (xhr.status != 200) {
    +            alert('Server error; try again.');
    +            return;
    +          }
    +          if (opts.shareRedirect) {
    +            window.location = opts.shareRedirect + xhr.responseText;
    +          }
    +          var path = '/p/' + xhr.responseText;
    +          var url = origin(window.location) + path;
    +
    +          for (var i = 0; i < shareCallbacks.length; i++) {
    +            shareCallbacks[i](url);
    +          }
    +          shareCallbacks = [];
    +
    +          if (shareURL) {
    +            shareURL
    +              .show()
    +              .val(url)
    +              .focus()
    +              .select();
    +
    +            if (rewriteHistory) {
    +              var historyData = { code: sharingData };
    +              window.history.pushState(historyData, '', path);
    +              pushedEmpty = false;
    +            }
    +          }
    +        },
    +      });
    +    }
    +
    +    $(opts.runEl).click(run);
    +    $(opts.fmtEl).click(fmt);
    +
    +    if (
    +      opts.shareEl !== null &&
    +      (opts.shareURLEl !== null || opts.shareRedirect !== null)
    +    ) {
    +      if (opts.shareURLEl) {
    +        shareURL = $(opts.shareURLEl).hide();
    +      }
    +      $(opts.shareEl).click(function() {
    +        share();
    +      });
    +    }
    +
    +    if (opts.toysEl !== null) {
    +      $(opts.toysEl).bind('change', function() {
    +        var toy = $(this).val();
    +        $.ajax('/doc/play/' + toy, {
    +          processData: false,
    +          type: 'GET',
    +          complete: function(xhr) {
    +            if (xhr.status != 200) {
    +              alert('Server error; try again.');
    +              return;
    +            }
    +            setBody(xhr.responseText);
    +          },
    +        });
    +      });
    +    }
    +  }
    +
    +  window.playground = playground;
    +})();
    +// Copyright 2012 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +function initPlayground(transport) {
    +  'use strict';
    +
    +  function text(node) {
    +    var s = '';
    +    for (var i = 0; i < node.childNodes.length; i++) {
    +      var n = node.childNodes[i];
    +      if (n.nodeType === 1) {
    +        if (n.tagName === 'BUTTON') continue;
    +        if (n.tagName === 'SPAN' && n.className === 'number') continue;
    +        if (n.tagName === 'DIV' || n.tagName === 'BR' || n.tagName === 'PRE') {
    +          s += '\n';
    +        }
    +        s += text(n);
    +        continue;
    +      }
    +      if (n.nodeType === 3) {
    +        s += n.nodeValue;
    +      }
    +    }
    +    return s.replace('\xA0', ' '); // replace non-breaking spaces
    +  }
    +
    +  // When presenter notes are enabled, the index passed
    +  // here will identify the playground to be synced
    +  function init(code, index) {
    +    var output = document.createElement('div');
    +    var outpre = document.createElement('pre');
    +    var running;
    +
    +    if ($ && $(output).resizable) {
    +      $(output).resizable({
    +        handles: 'n,w,nw',
    +        minHeight: 27,
    +        minWidth: 135,
    +        maxHeight: 608,
    +        maxWidth: 990,
    +      });
    +    }
    +
    +    function onKill() {
    +      if (running) running.Kill();
    +      if (window.notesEnabled) updatePlayStorage('onKill', index);
    +    }
    +
    +    function onRun(e) {
    +      var sk = e.shiftKey || localStorage.getItem('play-shiftKey') === 'true';
    +      if (running) running.Kill();
    +      output.style.display = 'block';
    +      outpre.textContent = '';
    +      run1.style.display = 'none';
    +      var options = { Race: sk };
    +      running = transport.Run(text(code), PlaygroundOutput(outpre), options);
    +      if (window.notesEnabled) updatePlayStorage('onRun', index, e);
    +    }
    +
    +    function onClose() {
    +      if (running) running.Kill();
    +      output.style.display = 'none';
    +      run1.style.display = 'inline-block';
    +      if (window.notesEnabled) updatePlayStorage('onClose', index);
    +    }
    +
    +    if (window.notesEnabled) {
    +      playgroundHandlers.onRun.push(onRun);
    +      playgroundHandlers.onClose.push(onClose);
    +      playgroundHandlers.onKill.push(onKill);
    +    }
    +
    +    var run1 = document.createElement('button');
    +    run1.textContent = 'Run';
    +    run1.className = 'run';
    +    run1.addEventListener('click', onRun, false);
    +    var run2 = document.createElement('button');
    +    run2.className = 'run';
    +    run2.textContent = 'Run';
    +    run2.addEventListener('click', onRun, false);
    +    var kill = document.createElement('button');
    +    kill.className = 'kill';
    +    kill.textContent = 'Kill';
    +    kill.addEventListener('click', onKill, false);
    +    var close = document.createElement('button');
    +    close.className = 'close';
    +    close.textContent = 'Close';
    +    close.addEventListener('click', onClose, false);
    +
    +    var button = document.createElement('div');
    +    button.classList.add('buttons');
    +    button.appendChild(run1);
    +    // Hack to simulate insertAfter
    +    code.parentNode.insertBefore(button, code.nextSibling);
    +
    +    var buttons = document.createElement('div');
    +    buttons.classList.add('buttons');
    +    buttons.appendChild(run2);
    +    buttons.appendChild(kill);
    +    buttons.appendChild(close);
    +
    +    output.classList.add('output');
    +    output.appendChild(buttons);
    +    output.appendChild(outpre);
    +    output.style.display = 'none';
    +    code.parentNode.insertBefore(output, button.nextSibling);
    +  }
    +
    +  var play = document.querySelectorAll('div.playground');
    +  for (var i = 0; i < play.length; i++) {
    +    init(play[i], i);
    +  }
    +}
    +
    +initPlayground(new SocketTransport());
    diff --git a/2023/04/03/quicksilver/bulletProofingCodeTDD_files/slides.js b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/slides.js
    new file mode 100644
    index 0000000..7c1229e
    --- /dev/null
    +++ b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/slides.js
    @@ -0,0 +1,635 @@
    +// Copyright 2012 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +var PERMANENT_URL_PREFIX = '/static/';
    +
    +var SLIDE_CLASSES = ['far-past', 'past', 'current', 'next', 'far-next'];
    +
    +var PM_TOUCH_SENSITIVITY = 15;
    +
    +var curSlide;
    +
    +/* ---------------------------------------------------------------------- */
    +/* classList polyfill by Eli Grey
    + * (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */
    +
    +if (
    +  typeof document !== 'undefined' &&
    +  !('classList' in document.createElement('a'))
    +) {
    +  (function(view) {
    +    var classListProp = 'classList',
    +      protoProp = 'prototype',
    +      elemCtrProto = (view.HTMLElement || view.Element)[protoProp],
    +      objCtr = Object;
    +    (strTrim =
    +      String[protoProp].trim ||
    +      function() {
    +        return this.replace(/^\s+|\s+$/g, '');
    +      }),
    +      (arrIndexOf =
    +        Array[protoProp].indexOf ||
    +        function(item) {
    +          for (var i = 0, len = this.length; i < len; i++) {
    +            if (i in this && this[i] === item) {
    +              return i;
    +            }
    +          }
    +          return -1;
    +        }),
    +      // Vendors: please allow content code to instantiate DOMExceptions
    +      (DOMEx = function(type, message) {
    +        this.name = type;
    +        this.code = DOMException[type];
    +        this.message = message;
    +      }),
    +      (checkTokenAndGetIndex = function(classList, token) {
    +        if (token === '') {
    +          throw new DOMEx(
    +            'SYNTAX_ERR',
    +            'An invalid or illegal string was specified'
    +          );
    +        }
    +        if (/\s/.test(token)) {
    +          throw new DOMEx(
    +            'INVALID_CHARACTER_ERR',
    +            'String contains an invalid character'
    +          );
    +        }
    +        return arrIndexOf.call(classList, token);
    +      }),
    +      (ClassList = function(elem) {
    +        var trimmedClasses = strTrim.call(elem.className),
    +          classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [];
    +        for (var i = 0, len = classes.length; i < len; i++) {
    +          this.push(classes[i]);
    +        }
    +        this._updateClassName = function() {
    +          elem.className = this.toString();
    +        };
    +      }),
    +      (classListProto = ClassList[protoProp] = []),
    +      (classListGetter = function() {
    +        return new ClassList(this);
    +      });
    +    // Most DOMException implementations don't allow calling DOMException's toString()
    +    // on non-DOMExceptions. Error's toString() is sufficient here.
    +    DOMEx[protoProp] = Error[protoProp];
    +    classListProto.item = function(i) {
    +      return this[i] || null;
    +    };
    +    classListProto.contains = function(token) {
    +      token += '';
    +      return checkTokenAndGetIndex(this, token) !== -1;
    +    };
    +    classListProto.add = function(token) {
    +      token += '';
    +      if (checkTokenAndGetIndex(this, token) === -1) {
    +        this.push(token);
    +        this._updateClassName();
    +      }
    +    };
    +    classListProto.remove = function(token) {
    +      token += '';
    +      var index = checkTokenAndGetIndex(this, token);
    +      if (index !== -1) {
    +        this.splice(index, 1);
    +        this._updateClassName();
    +      }
    +    };
    +    classListProto.toggle = function(token) {
    +      token += '';
    +      if (checkTokenAndGetIndex(this, token) === -1) {
    +        this.add(token);
    +      } else {
    +        this.remove(token);
    +      }
    +    };
    +    classListProto.toString = function() {
    +      return this.join(' ');
    +    };
    +
    +    if (objCtr.defineProperty) {
    +      var classListPropDesc = {
    +        get: classListGetter,
    +        enumerable: true,
    +        configurable: true,
    +      };
    +      try {
    +        objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
    +      } catch (ex) {
    +        // IE 8 doesn't support enumerable:true
    +        if (ex.number === -0x7ff5ec54) {
    +          classListPropDesc.enumerable = false;
    +          objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
    +        }
    +      }
    +    } else if (objCtr[protoProp].__defineGetter__) {
    +      elemCtrProto.__defineGetter__(classListProp, classListGetter);
    +    }
    +  })(self);
    +}
    +/* ---------------------------------------------------------------------- */
    +
    +/* Slide movement */
    +
    +function hideHelpText() {
    +  document.getElementById('help').style.display = 'none';
    +}
    +
    +function getSlideEl(no) {
    +  if (no < 0 || no >= slideEls.length) {
    +    return null;
    +  } else {
    +    return slideEls[no];
    +  }
    +}
    +
    +function updateSlideClass(slideNo, className) {
    +  var el = getSlideEl(slideNo);
    +
    +  if (!el) {
    +    return;
    +  }
    +
    +  if (className) {
    +    el.classList.add(className);
    +  }
    +
    +  for (var i in SLIDE_CLASSES) {
    +    if (className != SLIDE_CLASSES[i]) {
    +      el.classList.remove(SLIDE_CLASSES[i]);
    +    }
    +  }
    +}
    +
    +function updateSlides() {
    +  if (window.trackPageview) window.trackPageview();
    +
    +  for (var i = 0; i < slideEls.length; i++) {
    +    switch (i) {
    +      case curSlide - 2:
    +        updateSlideClass(i, 'far-past');
    +        break;
    +      case curSlide - 1:
    +        updateSlideClass(i, 'past');
    +        break;
    +      case curSlide:
    +        updateSlideClass(i, 'current');
    +        break;
    +      case curSlide + 1:
    +        updateSlideClass(i, 'next');
    +        break;
    +      case curSlide + 2:
    +        updateSlideClass(i, 'far-next');
    +        break;
    +      default:
    +        updateSlideClass(i);
    +        break;
    +    }
    +  }
    +
    +  triggerLeaveEvent(curSlide - 1);
    +  triggerEnterEvent(curSlide);
    +
    +  window.setTimeout(function() {
    +    // Hide after the slide
    +    disableSlideFrames(curSlide - 2);
    +  }, 301);
    +
    +  enableSlideFrames(curSlide - 1);
    +  enableSlideFrames(curSlide + 2);
    +
    +  updateHash();
    +}
    +
    +function prevSlide() {
    +  hideHelpText();
    +  if (curSlide > 0) {
    +    curSlide--;
    +
    +    updateSlides();
    +  }
    +
    +  if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide);
    +}
    +
    +function nextSlide() {
    +  hideHelpText();
    +  if (curSlide < slideEls.length - 1) {
    +    curSlide++;
    +
    +    updateSlides();
    +  }
    +
    +  if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide);
    +}
    +
    +/* Slide events */
    +
    +function triggerEnterEvent(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var onEnter = el.getAttribute('onslideenter');
    +  if (onEnter) {
    +    new Function(onEnter).call(el);
    +  }
    +
    +  var evt = document.createEvent('Event');
    +  evt.initEvent('slideenter', true, true);
    +  evt.slideNumber = no + 1; // Make it readable
    +
    +  el.dispatchEvent(evt);
    +}
    +
    +function triggerLeaveEvent(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var onLeave = el.getAttribute('onslideleave');
    +  if (onLeave) {
    +    new Function(onLeave).call(el);
    +  }
    +
    +  var evt = document.createEvent('Event');
    +  evt.initEvent('slideleave', true, true);
    +  evt.slideNumber = no + 1; // Make it readable
    +
    +  el.dispatchEvent(evt);
    +}
    +
    +/* Touch events */
    +
    +function handleTouchStart(event) {
    +  if (event.touches.length == 1) {
    +    touchDX = 0;
    +    touchDY = 0;
    +
    +    touchStartX = event.touches[0].pageX;
    +    touchStartY = event.touches[0].pageY;
    +
    +    document.body.addEventListener('touchmove', handleTouchMove, true);
    +    document.body.addEventListener('touchend', handleTouchEnd, true);
    +  }
    +}
    +
    +function handleTouchMove(event) {
    +  if (event.touches.length > 1) {
    +    cancelTouch();
    +  } else {
    +    touchDX = event.touches[0].pageX - touchStartX;
    +    touchDY = event.touches[0].pageY - touchStartY;
    +    event.preventDefault();
    +  }
    +}
    +
    +function handleTouchEnd(event) {
    +  var dx = Math.abs(touchDX);
    +  var dy = Math.abs(touchDY);
    +
    +  if (dx > PM_TOUCH_SENSITIVITY && dy < (dx * 2) / 3) {
    +    if (touchDX > 0) {
    +      prevSlide();
    +    } else {
    +      nextSlide();
    +    }
    +  }
    +
    +  cancelTouch();
    +}
    +
    +function cancelTouch() {
    +  document.body.removeEventListener('touchmove', handleTouchMove, true);
    +  document.body.removeEventListener('touchend', handleTouchEnd, true);
    +}
    +
    +/* Preloading frames */
    +
    +function disableSlideFrames(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var frames = el.getElementsByTagName('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    disableFrame(frame);
    +  }
    +}
    +
    +function enableSlideFrames(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var frames = el.getElementsByTagName('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    enableFrame(frame);
    +  }
    +}
    +
    +function disableFrame(frame) {
    +  frame.src = 'about:blank';
    +}
    +
    +function enableFrame(frame) {
    +  var src = frame._src;
    +
    +  if (frame.src != src && src != 'about:blank') {
    +    frame.src = src;
    +  }
    +}
    +
    +function setupFrames() {
    +  var frames = document.querySelectorAll('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    frame._src = frame.src;
    +    disableFrame(frame);
    +  }
    +
    +  enableSlideFrames(curSlide);
    +  enableSlideFrames(curSlide + 1);
    +  enableSlideFrames(curSlide + 2);
    +}
    +
    +function setupInteraction() {
    +  /* Clicking and tapping */
    +
    +  var el = document.createElement('div');
    +  el.className = 'slide-area';
    +  el.id = 'prev-slide-area';
    +  el.addEventListener('click', prevSlide, false);
    +  document.querySelector('section.slides').appendChild(el);
    +
    +  var el = document.createElement('div');
    +  el.className = 'slide-area';
    +  el.id = 'next-slide-area';
    +  el.addEventListener('click', nextSlide, false);
    +  document.querySelector('section.slides').appendChild(el);
    +
    +  /* Swiping */
    +
    +  document.body.addEventListener('touchstart', handleTouchStart, false);
    +}
    +
    +/* Hash functions */
    +
    +function getCurSlideFromHash() {
    +  var slideNo = parseInt(location.hash.substr(1));
    +
    +  if (slideNo) {
    +    curSlide = slideNo - 1;
    +  } else {
    +    curSlide = 0;
    +  }
    +}
    +
    +function updateHash() {
    +  location.replace('#' + (curSlide + 1));
    +}
    +
    +/* Event listeners */
    +
    +function handleBodyKeyDown(event) {
    +  // If we're in a code element, only handle pgup/down.
    +  var inCode = event.target.classList.contains('code');
    +
    +  switch (event.keyCode) {
    +    case 78: // 'N' opens presenter notes window
    +      if (!inCode && notesEnabled) toggleNotesWindow();
    +      break;
    +    case 72: // 'H' hides the help text
    +    case 27: // escape key
    +      if (!inCode) hideHelpText();
    +      break;
    +
    +    case 39: // right arrow
    +    case 13: // Enter
    +    case 32: // space
    +      if (inCode) break;
    +    case 34: // PgDn
    +      nextSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 37: // left arrow
    +    case 8: // Backspace
    +      if (inCode) break;
    +    case 33: // PgUp
    +      prevSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 40: // down arrow
    +      if (inCode) break;
    +      nextSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 38: // up arrow
    +      if (inCode) break;
    +      prevSlide();
    +      event.preventDefault();
    +      break;
    +  }
    +}
    +
    +function scaleSmallViewports() {
    +  var el = document.querySelector('section.slides');
    +  var transform = '';
    +  var sWidthPx = 1250;
    +  var sHeightPx = 750;
    +  var sAspectRatio = sWidthPx / sHeightPx;
    +  var wAspectRatio = window.innerWidth / window.innerHeight;
    +
    +  if (wAspectRatio <= sAspectRatio && window.innerWidth < sWidthPx) {
    +    transform = 'scale(' + window.innerWidth / sWidthPx + ')';
    +  } else if (window.innerHeight < sHeightPx) {
    +    transform = 'scale(' + window.innerHeight / sHeightPx + ')';
    +  }
    +  el.style.transform = transform;
    +}
    +
    +function addEventListeners() {
    +  document.addEventListener('keydown', handleBodyKeyDown, false);
    +  var resizeTimeout;
    +  window.addEventListener('resize', function() {
    +    // throttle resize events
    +    window.clearTimeout(resizeTimeout);
    +    resizeTimeout = window.setTimeout(function() {
    +      resizeTimeout = null;
    +      scaleSmallViewports();
    +    }, 50);
    +  });
    +
    +  // Force reset transform property of section.slides when printing page.
    +  // Use both onbeforeprint and matchMedia for compatibility with different browsers.
    +  var beforePrint = function() {
    +    var el = document.querySelector('section.slides');
    +    el.style.transform = '';
    +  };
    +  window.onbeforeprint = beforePrint;
    +  if (window.matchMedia) {
    +    var mediaQueryList = window.matchMedia('print');
    +    mediaQueryList.addListener(function(mql) {
    +      if (mql.matches) beforePrint();
    +    });
    +  }
    +}
    +
    +/* Initialization */
    +
    +function addFontStyle() {
    +  var el = document.createElement('link');
    +  el.rel = 'stylesheet';
    +  el.type = 'text/css';
    +  el.href =
    +    '//fonts.googleapis.com/css?family=' +
    +    'Open+Sans:regular,semibold,italic,italicsemibold|Droid+Sans+Mono';
    +
    +  document.body.appendChild(el);
    +}
    +
    +function addGeneralStyle() {
    +  var el = document.createElement('link');
    +  el.rel = 'stylesheet';
    +  el.type = 'text/css';
    +  el.href = PERMANENT_URL_PREFIX + 'styles.css';
    +  document.body.appendChild(el);
    +
    +  var el = document.createElement('meta');
    +  el.name = 'viewport';
    +  el.content = 'width=device-width,height=device-height,initial-scale=1';
    +  document.querySelector('head').appendChild(el);
    +
    +  var el = document.createElement('meta');
    +  el.name = 'apple-mobile-web-app-capable';
    +  el.content = 'yes';
    +  document.querySelector('head').appendChild(el);
    +
    +  scaleSmallViewports();
    +}
    +
    +function handleDomLoaded() {
    +  slideEls = document.querySelectorAll('section.slides > article');
    +
    +  setupFrames();
    +
    +  addFontStyle();
    +  addGeneralStyle();
    +  addEventListeners();
    +
    +  updateSlides();
    +
    +  setupInteraction();
    +
    +  if (
    +    window.location.hostname == 'localhost' ||
    +    window.location.hostname == '127.0.0.1' ||
    +    window.location.hostname == '::1'
    +  ) {
    +    hideHelpText();
    +  }
    +
    +  document.body.classList.add('loaded');
    +
    +  setupNotesSync();
    +}
    +
    +function initialize() {
    +  getCurSlideFromHash();
    +
    +  if (window['_DEBUG']) {
    +    PERMANENT_URL_PREFIX = '../';
    +  }
    +
    +  if (window['_DCL']) {
    +    handleDomLoaded();
    +  } else {
    +    document.addEventListener('DOMContentLoaded', handleDomLoaded, false);
    +  }
    +}
    +
    +// If ?debug exists then load the script relative instead of absolute
    +if (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) {
    +  document.addEventListener(
    +    'DOMContentLoaded',
    +    function() {
    +      // Avoid missing the DomContentLoaded event
    +      window['_DCL'] = true;
    +    },
    +    false
    +  );
    +
    +  window['_DEBUG'] = true;
    +  var script = document.createElement('script');
    +  script.type = 'text/javascript';
    +  script.src = '../slides.js';
    +  var s = document.getElementsByTagName('script')[0];
    +  s.parentNode.insertBefore(script, s);
    +
    +  // Remove this script
    +  s.parentNode.removeChild(s);
    +} else {
    +  initialize();
    +}
    +
    +/* Synchronize windows when notes are enabled */
    +
    +function setupNotesSync() {
    +  if (!notesEnabled) return;
    +
    +  function setupPlayResizeSync() {
    +    var out = document.getElementsByClassName('output');
    +    for (var i = 0; i < out.length; i++) {
    +      $(out[i]).bind('resize', function(event) {
    +        if ($(event.target).hasClass('ui-resizable')) {
    +          localStorage.setItem('play-index', i);
    +          localStorage.setItem('output-style', out[i].style.cssText);
    +        }
    +      });
    +    }
    +  }
    +  function setupPlayCodeSync() {
    +    var play = document.querySelectorAll('div.playground');
    +    for (var i = 0; i < play.length; i++) {
    +      play[i].addEventListener('input', inputHandler, false);
    +
    +      function inputHandler(e) {
    +        localStorage.setItem('play-index', i);
    +        localStorage.setItem('play-code', e.target.innerHTML);
    +      }
    +    }
    +  }
    +
    +  setupPlayCodeSync();
    +  setupPlayResizeSync();
    +  localStorage.setItem(destSlideKey(), curSlide);
    +  window.addEventListener('storage', updateOtherWindow, false);
    +}
    +
    +// An update to local storage is caught only by the other window
    +// The triggering window does not handle any sync actions
    +function updateOtherWindow(e) {
    +  // Ignore remove storage events which are not meant to update the other window
    +  var isRemoveStorageEvent = !e.newValue;
    +  if (isRemoveStorageEvent) return;
    +
    +  var destSlide = localStorage.getItem(destSlideKey());
    +  while (destSlide > curSlide) {
    +    nextSlide();
    +  }
    +  while (destSlide < curSlide) {
    +    prevSlide();
    +  }
    +
    +  updatePlay(e);
    +  updateNotes();
    +}
    diff --git a/2023/04/03/quicksilver/bulletProofingCodeTDD_files/styles.css b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/styles.css
    new file mode 100644
    index 0000000..47c9f19
    --- /dev/null
    +++ b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/styles.css
    @@ -0,0 +1,558 @@
    +@media screen {
    +  /* Framework */
    +  html {
    +    height: 100%;
    +  }
    +
    +  body {
    +    margin: 0;
    +    padding: 0;
    +
    +    display: block !important;
    +
    +    height: 100%;
    +    height: 100vh;
    +
    +    overflow: hidden;
    +
    +    background: rgb(215, 215, 215);
    +    background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -webkit-gradient(
    +      radial,
    +      50% 50%,
    +      0,
    +      50% 50%,
    +      500,
    +      from(rgb(240, 240, 240)),
    +      to(rgb(190, 190, 190))
    +    );
    +
    +    -webkit-font-smoothing: antialiased;
    +  }
    +
    +  .slides {
    +    width: 100%;
    +    height: 100%;
    +    left: 0;
    +    top: 0;
    +
    +    position: absolute;
    +
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +
    +  .slides > article {
    +    display: block;
    +
    +    position: absolute;
    +    overflow: hidden;
    +
    +    width: 900px;
    +    height: 700px;
    +
    +    left: 50%;
    +    top: 50%;
    +
    +    margin-left: -450px;
    +    margin-top: -350px;
    +
    +    padding: 40px 60px;
    +
    +    box-sizing: border-box;
    +    -o-box-sizing: border-box;
    +    -moz-box-sizing: border-box;
    +    -webkit-box-sizing: border-box;
    +
    +    border-radius: 10px;
    +    -o-border-radius: 10px;
    +    -moz-border-radius: 10px;
    +    -webkit-border-radius: 10px;
    +
    +    background-color: white;
    +
    +    border: 1px solid rgba(0, 0, 0, 0.3);
    +
    +    transition: transform 0.3s ease-out;
    +    -o-transition: -o-transform 0.3s ease-out;
    +    -moz-transition: -moz-transform 0.3s ease-out;
    +    -webkit-transition: -webkit-transform 0.3s ease-out;
    +  }
    +  .slides.layout-widescreen > article {
    +    margin-left: -550px;
    +    width: 1100px;
    +  }
    +  .slides.layout-faux-widescreen > article {
    +    margin-left: -550px;
    +    width: 1100px;
    +
    +    padding: 40px 160px;
    +  }
    +
    +  .slides.layout-widescreen > article:not(.nobackground):not(.biglogo),
    +  .slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) {
    +    background-position-x: 0, 840px;
    +  }
    +
    +  /* Clickable/tappable areas */
    +
    +  .slide-area {
    +    z-index: 1000;
    +
    +    position: absolute;
    +    left: 0;
    +    top: 0;
    +    width: 150px;
    +    height: 700px;
    +
    +    left: 50%;
    +    top: 50%;
    +
    +    cursor: pointer;
    +    margin-top: -350px;
    +
    +    tap-highlight-color: transparent;
    +    -o-tap-highlight-color: transparent;
    +    -moz-tap-highlight-color: transparent;
    +    -webkit-tap-highlight-color: transparent;
    +  }
    +  #prev-slide-area {
    +    margin-left: -550px;
    +  }
    +  #next-slide-area {
    +    margin-left: 400px;
    +  }
    +  .slides.layout-widescreen #prev-slide-area,
    +  .slides.layout-faux-widescreen #prev-slide-area {
    +    margin-left: -650px;
    +  }
    +  .slides.layout-widescreen #next-slide-area,
    +  .slides.layout-faux-widescreen #next-slide-area {
    +    margin-left: 500px;
    +  }
    +
    +  /* Slides */
    +
    +  .slides > article {
    +    display: none;
    +  }
    +  .slides > article.far-past {
    +    display: block;
    +    transform: translate(-2040px);
    +    -o-transform: translate(-2040px);
    +    -moz-transform: translate(-2040px);
    +    -webkit-transform: translate3d(-2040px, 0, 0);
    +  }
    +  .slides > article.past {
    +    display: block;
    +    transform: translate(-1020px);
    +    -o-transform: translate(-1020px);
    +    -moz-transform: translate(-1020px);
    +    -webkit-transform: translate3d(-1020px, 0, 0);
    +  }
    +  .slides > article.current {
    +    display: block;
    +    transform: translate(0);
    +    -o-transform: translate(0);
    +    -moz-transform: translate(0);
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +  .slides > article.next {
    +    display: block;
    +    transform: translate(1020px);
    +    -o-transform: translate(1020px);
    +    -moz-transform: translate(1020px);
    +    -webkit-transform: translate3d(1020px, 0, 0);
    +  }
    +  .slides > article.far-next {
    +    display: block;
    +    transform: translate(2040px);
    +    -o-transform: translate(2040px);
    +    -moz-transform: translate(2040px);
    +    -webkit-transform: translate3d(2040px, 0, 0);
    +  }
    +
    +  .slides.layout-widescreen > article.far-past,
    +  .slides.layout-faux-widescreen > article.far-past {
    +    display: block;
    +    transform: translate(-2260px);
    +    -o-transform: translate(-2260px);
    +    -moz-transform: translate(-2260px);
    +    -webkit-transform: translate3d(-2260px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.past,
    +  .slides.layout-faux-widescreen > article.past {
    +    display: block;
    +    transform: translate(-1130px);
    +    -o-transform: translate(-1130px);
    +    -moz-transform: translate(-1130px);
    +    -webkit-transform: translate3d(-1130px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.current,
    +  .slides.layout-faux-widescreen > article.current {
    +    display: block;
    +    transform: translate(0);
    +    -o-transform: translate(0);
    +    -moz-transform: translate(0);
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.next,
    +  .slides.layout-faux-widescreen > article.next {
    +    display: block;
    +    transform: translate(1130px);
    +    -o-transform: translate(1130px);
    +    -moz-transform: translate(1130px);
    +    -webkit-transform: translate3d(1130px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.far-next,
    +  .slides.layout-faux-widescreen > article.far-next {
    +    display: block;
    +    transform: translate(2260px);
    +    -o-transform: translate(2260px);
    +    -moz-transform: translate(2260px);
    +    -webkit-transform: translate3d(2260px, 0, 0);
    +  }
    +}
    +
    +@media print {
    +  /* Set page layout */
    +  @page {
    +    size: A4 landscape;
    +  }
    +
    +  body {
    +    display: block !important;
    +  }
    +
    +  .slides > article {
    +    display: block;
    +
    +    position: relative;
    +
    +    page-break-inside: never;
    +    page-break-after: always;
    +
    +    overflow: hidden;
    +  }
    +
    +  h2 {
    +    position: static !important;
    +    margin-top: 400px !important;
    +    margin-bottom: 100px !important;
    +  }
    +
    +  pre {
    +    background: rgb(240, 240, 240);
    +  }
    +
    +  /* Add explicit links */
    +  a:link:after,
    +  a:visited:after {
    +    content: ' (' attr(href) ') ';
    +    font-size: 50%;
    +  }
    +
    +  #help {
    +    display: none;
    +    visibility: hidden;
    +  }
    +}
    +
    +/* Styles for slides */
    +
    +.slides > article {
    +  font-family: 'Open Sans', Arial, sans-serif;
    +
    +  color: black;
    +  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
    +
    +  font-size: 26px;
    +  line-height: 36px;
    +
    +  letter-spacing: -1px;
    +}
    +
    +b {
    +  font-weight: 600;
    +}
    +
    +a {
    +  color: rgb(0, 102, 204);
    +  text-decoration: none;
    +}
    +a:visited {
    +  color: rgba(0, 102, 204, 0.75);
    +}
    +a:hover {
    +  color: black;
    +}
    +
    +p {
    +  margin: 0;
    +  padding: 0;
    +
    +  margin-top: 20px;
    +}
    +p:first-child {
    +  margin-top: 0;
    +}
    +
    +h1 {
    +  font-size: 60px;
    +  line-height: 60px;
    +
    +  padding: 0;
    +  margin: 0;
    +  margin-top: 200px;
    +  margin-bottom: 5px;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -3px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +h2 {
    +  font-size: 45px;
    +  line-height: 45px;
    +
    +  position: absolute;
    +  bottom: 150px;
    +
    +  padding: 0;
    +  margin: 0;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -2px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +h3 {
    +  font-size: 30px;
    +  line-height: 36px;
    +
    +  padding: 0;
    +  margin: 0;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -1px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +ul {
    +  margin: 0;
    +  padding: 0;
    +  margin-top: 20px;
    +  margin-left: 1.5em;
    +}
    +li {
    +  padding: 0;
    +  margin: 0 0 0.5em 0;
    +}
    +
    +div.code, div.output {
    +  margin: 0;
    +  padding: 0;
    +}
    +
    +pre {
    +  padding: 5px 10px;
    +  margin-top: 20px;
    +  margin-bottom: 20px;
    +  overflow: hidden;
    +
    +  background: rgb(240, 240, 240);
    +  border: 1px solid rgb(224, 224, 224);
    +
    +  font-family: 'Droid Sans Mono', 'Courier New', monospace;
    +  font-size: 18px;
    +  line-height: 24px;
    +  letter-spacing: -1px;
    +
    +  color: black;
    +}
    +
    +pre.numbers span:before {
    +  content: attr(num);
    +  margin-right: 1em;
    +  display: inline-block;
    +}
    +
    +code {
    +  font-size: 95%;
    +  font-family: 'Droid Sans Mono', 'Courier New', monospace;
    +
    +  color: black;
    +}
    +
    +pre code {
    +  font-size: 100%;
    +}
    +
    +article > .image,
    +article > .video {
    +  text-align: center;
    +  margin-top: 40px;
    +}
    +
    +article.background {
    +  background-size: contain;
    +  background-repeat: round;
    +}
    +
    +table {
    +  width: 100%;
    +  border-collapse: collapse;
    +  margin-top: 40px;
    +}
    +th {
    +  font-weight: 600;
    +  text-align: left;
    +}
    +td,
    +th {
    +  border: 1px solid rgb(224, 224, 224);
    +  padding: 5px 10px;
    +  vertical-align: top;
    +}
    +
    +p.link {
    +  margin-left: 20px;
    +}
    +
    +.pagenumber {
    +  color: #8c8c8c;
    +  font-size: 75%;
    +  position: absolute;
    +  bottom: 0px;
    +  right: 10px;
    +}
    +
    +/* Code */
    +pre {
    +  outline: 0px solid transparent;
    +}
    +div.playground {
    +  position: relative;
    +}
    +div.output {
    +  position: absolute;
    +  left: 50%;
    +  top: 50%;
    +  right: 40px;
    +  bottom: 40px;
    +  background: #202020;
    +  padding: 5px 10px;
    +  z-index: 2;
    +
    +  border-radius: 10px;
    +  -o-border-radius: 10px;
    +  -moz-border-radius: 10px;
    +  -webkit-border-radius: 10px;
    +}
    +div.output pre {
    +  margin: 0;
    +  padding: 0;
    +  background: none;
    +  border: none;
    +  width: 100%;
    +  height: 100%;
    +  overflow: auto;
    +}
    +div.output .stdout,
    +div.output pre {
    +  color: #e6e6e6;
    +}
    +div.output .stderr,
    +div.output .error {
    +  color: rgb(255, 200, 200);
    +}
    +div.output .system,
    +div.output .exit {
    +  color: rgb(255, 230, 120);
    +}
    +.buttons {
    +  position: relative;
    +  float: right;
    +  top: -60px;
    +  right: 10px;
    +}
    +div.output .buttons {
    +  position: absolute;
    +  float: none;
    +  top: auto;
    +  right: 5px;
    +  bottom: 5px;
    +}
    +
    +/* Presenter details */
    +.presenter {
    +  margin-top: 20px;
    +}
    +.presenter p,
    +.presenter .link {
    +  margin: 0;
    +  font-size: 28px;
    +  line-height: 1.2em;
    +}
    +
    +/* Output resize details */
    +.ui-resizable-handle {
    +  position: absolute;
    +}
    +.ui-resizable-n {
    +  cursor: n-resize;
    +  height: 7px;
    +  width: 100%;
    +  top: -5px;
    +  left: 0;
    +}
    +.ui-resizable-w {
    +  cursor: w-resize;
    +  width: 7px;
    +  left: -5px;
    +  top: 0;
    +  height: 100%;
    +}
    +.ui-resizable-nw {
    +  cursor: nw-resize;
    +  width: 9px;
    +  height: 9px;
    +  left: -5px;
    +  top: -5px;
    +}
    +iframe {
    +  border: none;
    +}
    +figcaption {
    +  color: #666;
    +  text-align: center;
    +  font-size: 0.75em;
    +}
    +
    +#help {
    +  font-family: 'Open Sans', Arial, sans-serif;
    +  text-align: center;
    +  color: white;
    +  background: #000;
    +  opacity: 0.5;
    +  position: fixed;
    +  bottom: 25px;
    +  left: 50px;
    +  right: 50px;
    +  padding: 20px;
    +
    +  border-radius: 10px;
    +  -o-border-radius: 10px;
    +  -moz-border-radius: 10px;
    +  -webkit-border-radius: 10px;
    +}
    diff --git a/2023/04/03/quicksilver/bulletProofingCodeTDD_files/thinkLikeAHacker.png b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/thinkLikeAHacker.png
    new file mode 100644
    index 0000000..4735085
    Binary files /dev/null and b/2023/04/03/quicksilver/bulletProofingCodeTDD_files/thinkLikeAHacker.png differ
    diff --git a/2023/04/03/quicksilver/bulletproofing.slide b/2023/04/03/quicksilver/bulletproofing.slide
    new file mode 100644
    index 0000000..d3ce263
    --- /dev/null
    +++ b/2023/04/03/quicksilver/bulletproofing.slide
    @@ -0,0 +1,283 @@
    +# Bullet proofing your code, products with better testing, dexterity and skills/finesse
    +Tags: go, testing, better skills
    +
    +Emmanuel T Odeke
    +Orijtech, Inc.
    +Mon 3 Apr 2023
    +emmanuel@orijtech.com
    +@odeke_et
    +
    +## Bullet proofing your code, with better testing, dexterity and skills/finesse
    +
    +## About myself
    +* Emmanuel T Odeke, CEO & Chief Builder at Orijtech, Inc.
    +* Core contributor to the Go programming language, observability, Cosmos-SDK and various cloud computing technologies
    +* Friend and contributor to QuickSilver: delighted and thankful for your great partnership business!
    +* Always learning and enjoys solving problems in all domains
    +* Optimistic about the future
    +* Believes in sharing as much information, skills, tips as possible to equip everyone with problem solving skills and also to learn!
    +* Proponent of testing code to prevent expensive retroactive fixes
    +
    +## Why this talk?
    +* Failures of code in production are so expensive, violating user trust, costing money, demoralizing teams, break ecosystems
    +* Our cybersecurity division [cyber.orijtech.com](https://cyber.orijtech.com) audited QuickSilver's code a couple of times in 2022, 2023 and we want y'all to be successful and scale -- put ourselves out of business
    +* Securing a product requires an all-inclusive mindset from the ground up
    +* In most cases, security falters due to being overwhelmed, a lack of knowledge, lack of the appropriate skills, inability to focus on core business logic, fighting fires, inability to respond in a reasonable time
    +* We've audited tons of code including cosmos-sdk, tendermint and related code
    +* Knowledge sharing and skills imparting is something we celebrate
    +* Prevent worst case scenarios by planning for them and mitigating them: stay a step ahead of disaster
    +
    +## Basis
    +* Most of your code is written in the Go programming language
    +* Regardless of language, code and products have to be tested sufficiently
    +* Software development is a distributed and highly collaborative process to produce a common work output implementing business logic
    +* Can't fix what you can't gauge/measure!!
    +* User trust and all kinds of trust are built from reliability, beauty, good taste, pragmatic problem solving; your consumers and team know that whoever is handling something will do great at it
    +* Skills division: Adam Smith put it succinctly in "Wealth of Nations" that division of labour, specialization and expertise are needed to produce high quality goods and scale them: you can't do everything
    +* Disaster strikes always but what matters is the ability to get back and fix things in a timely manner
    +* Curiosity killed the cat, but for humans curiosity is a marvel that will allow you to always win!
    +* Everyone struggles continuously trying to have reliable and more secure products
    +
    +## What goes wrong?
    +
    +## Lack of finesse/dexterity/skill
    +* Inability to bend and control your environment is a big reason why folks cut corners; they'd rather spend that time developing features that are within inches of their reach rather than banging their heads against the wall
    +* This is usually the biggest problem facing most developers
    +* In order for one to get their code tested, they need dexterity and knowledge of how to setup their code so that it can operate effectively
    +* We want to go from zero to Hero!!
    +
    + +## Steps to getting better? + +## Test Driven Development +* Software methodology in which before code is written, figure out inputs, outputs and tests for correctness +* In practice most people conveniently write code firstly but before submitting code for code review, send related tests +* Write as many unique tests that cover various parts of your code +* More unique cases that take diverse paths, make your code more robust +* Find and fix those failures before they find you +* Crashes, panics, exploits are ways that malicious actors can get into your systems or take them out and erode user trust +* Rigorous testin: think of tests as a guide to make your products much safer; a cultural paradigm shift +* Measuring rigor can happen by using the right tools to exorcise your code +* Enables you to follow specifications and find out their limits which is much more effective than fiddling for ages + +## How to get there? + +## Unit tests +* Unit tests ensure that specific behaviors can be empirically verified: `add(1, 10)=11`, `add(10, -11)=-1` +* Useful as sanity tests to assert against target behavior +* However, can be deceptively comforting given that most code is complex and the human mind usually cannot +think of all ways to exorcise code paths and inputs +* A group of unit tests can give some good assurances as we can enumerate as many test inputs +* How can we scale unit testing? How do we group a collection of such tests and pass in well known inputs and assert on outputs? + +## Table tests +* Table tests are a collection of unit test inputs and desired outputs that we assert on to ensure functional integrity in a much more scalable way than just 1 unit test per function + +.code table_test.go + +## Can't fix what we can't measure :-( + +## Test coverage measurements +* Unknowns beget unknowns: untested behavior is a death trap for your code in production +* You can't fix what you can't measure! +* Think of a way to illuminate darkness as you keep improving your test cases +* Go has just this tool `go test -coverprofile=out.cover ./... && go tool cover -html=out.cover` +* There are commercial tools like [codecov](https://about.codecov.io/) that you can link up to your CI/CD process to set targets for minimums required before any merge + +## Coverage pictorial: red uncovered, green covered by tests + +
    + +## Some code review + +.play buggy.go + +## See that panic? We could patch it! +* However, we are playing cat and mouse and as code so much more complex, we need a breath of fresh +air that's much more scalable +* How many failures can we spot in there immediately? + +## Automated and guided test coverage? + +## Fuzzing +* An advanced automated testing technique that mostly operates by intelligently mutating known inputs and feeds them into code being tested, measuring changes in test coverage, watching out for panics, crashes, memory issues and other negative conditions: guided by the tester +* Fuzzing uses the power of the repetitive nature of computers along with some guiding from a human who described a score that'll reveal negative or positive examples so that the genetic mutation algorithms can work +* Go has native fuzzing support with the "testing" package and the "testing.F" type +* A huge nod to the excellent [Dmitry Vyukov](https://twitter.com/dvyukov) whose pioneering work wth [dvyukov/go-fuzz](https://github.com/dvyukov/go-fuzz) has made Go so much safer and made fuzzing main stream +* Google's [oss-fuzz](https://google.github.io/oss-fuzz/) is an excellent framework for automated fuzzing and at Orijtech Inc. put up the cosmos-sdk and tendermint plus other repositories for continuous fuzzing + +## Fuzzing in action +* Following Go's guides at [testing.F]() we can write a fuzzer which we shall feed in initial inputs + +.code fuzz_test.go + +## Run the fuzzer +.code fuzz_output.txt + +## Data race detector +* Always enable `go test -race` in your Go tests +* It'll save you tons of grief and help you catch insidious bugs! + +## Hermetic networking +* Mutating, reading, erasing data in production poses financial, regulatory, privacy burdens and slow down growth and development of your business products +* "Hermetic networking" just means isolated/controlled netwoorks that don't have to hit production environments +* You can use a combination of mock servers, HTTP, gRPC servers, containers to run complex code all within your local network +* Hermetic networking will allow you to get the reigns of all kinds of networks +* Let's focus on HTTP and gRPC; same principles apply to other transports and frameworks + +## HTTP taming +* As Orijtech Inc, we published in May 2020 a guide ["Taming net/http"](https://medium.com/orijtech-developers/taming-net-http-b946edfda562) which can help you get the finesse to deal with HTTP networking and help you with keeping connections within your local/hermetic network +* With these skills you'll be able to test out your HTTP services against server specifications and not have to hit production databases + +## HTTP client wiring for hermetic network +.play http_client_roundtripper.go + +## HTTP server wiring for hermetic network +.play http_server.go + +## gRPC server wiring for hermetic network + +.code grpc_server.go + +## gRPC client wiring for hermetic network + +.code grpc_client.go + +## Container deployment harness and testing in code +.code container_1.go + +## Container deployment harness and testing in code +.code container_2.go + +## Container deployment harness and testing in code +.code container_3.go + +## Benchmarking + +## Benchmarking +* Performance is key for so much code out there +* You can't fix what you can't measure especially for expensive components +* Go provides first class support for benchmarking +* Let's look at some piece of code + +.code bytes_naive.go + +## Code review? +* It looks sound and it passes code review, right? +* Can we do much better? +* What if I told you that that code is quite inefficient and it’s algorithmic complexity is quadratic? +* How do we know if we’ve made an improvement? How can we compare its performance with that from the standard library’s bytes.Index? +* Answering such questions naively can cause pointless ego trips and rifts on the team. You definitely can’t answer those questions unless you have an eye for algorithms and when you make performance improvements you need to quantify them. + +## Let's see the benchmarks to resolve all arguments +.code bench_bytes_test.go + +## Running them +.code bench_bytes_benches_test.go +.code bench_output.txt + +## before.txt +``` +BenchmarkIndex-8 2098716 549.8 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 2142109 540.1 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 2126098 538.4 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 2194460 557.7 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 2185105 552.3 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 2137668 541.7 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 2191056 545.6 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 2144031 546.5 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 2162593 552.2 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 2185425 544.0 ns/op 24 B/op 3 allocs/op +``` + +## after.txt +``` +BenchmarkIndex-8 8374387 141.2 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 8466294 137.2 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 8444934 147.9 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 7422019 137.5 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 8486536 134.6 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 8304022 144.2 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 8451594 142.5 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 8867498 134.8 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 8463555 131.4 ns/op 24 B/op 3 allocs/op +BenchmarkIndex-8 9168367 135.3 ns/op 24 B/op 3 allocs/op +``` + +## Benchmark shoot outs +``` +$ benchstat before.txt after.txt +name old time/op new time/op delta +Index-8 547ns ± 2% 139ns ± 7% -74.64% (p=0.000 n=10+10) + +name old alloc/op new alloc/op delta +Index-8 24.0B ± 0% 24.0B ± 0% ~ (all equal) + +name old allocs/op new allocs/op delta +Index-8 3.00 ± 0% 3.00 ± 0% ~ (all equal) +``` + +## Benchmarking recommendations +* For continuous benchmarking, we recommend Orijtech’s very own tool bencher (*sure this seems like a shameless plug but as of March 28th 2023, it is the only continuous benchmarking tool on the market and one that we’ve put in lots of time and expertise into refining, with dedicated quiet machines*) please see [https://bencher.orijtech.com/](https://bencher.orijtech.com/) +* for a sample please see some graphs it generates please see [https://dashboard.bencher.orijtech.com/benchmark/831d9385b36d4729a2430d1bea56538e](https://dashboard.bencher.orijtech.com/benchmark/831d9385b36d4729a2430d1bea56538e) in which we have a clear win + +## Benchmark result +
    + +## Static analyzers +* Code that analyses the structure of your code without running it, pointing out faulty issues +* Go comes equipped with `go test` which has a bunch of static analyzers already included +* Please check out the [Go static analysis package golang.orgx/tools/go/analysis](https://pkg.go.dev/golang.org/x/tools/go/analysis) +* We recommend using tools like [staticcheck]() or Orijtech's very own [staticmajor]() + +## Vulnerability scanners +* Vulnerability scanners when added to your build or continuous integration (CI) process will help you proactively flag code that's been +crowd sourced and reported responsibly to a collection of vulnerability databases such as the National Vulnerability Database (NVD) +* Go provides support for the [Go vulnerability scanner](https://go.dev/blog/vuln) which you can add by +* `go install golang.org/x/vuln/cmd/govulncheck@latest && govulncheck ./...` +* Cybersecurity is a continuous goal whose landscape changes every single day as more software is written, new vulnerabilities are found + +## Supply chain security +* Most software is imported from libraries written not but us but by authors we choose to indirectly trust +* In an ever changing and complex world in which software changes every second, it is a huge risk that some brittle piece of code in the supply chain could be made vulnerable +* Please visit our page for [supply chain security](https://cyber.orijtech.com/scsec/) +* A simple mutation of something like "crypto/rand".Reader being changed in some obscure, hard to find dependency can pwn your entire program please see [https://gist.github.com/odeke-em/dc1ce9f680c5bb6e17aa4e9a0a3efab9](https://gist.github.com/odeke-em/dc1ce9f680c5bb6e17aa4e9a0a3efab9) + +## Supply chain pwn +.play rand_pwn.go + +## Introspective tooling like runtime tracing, profiling and observability + +* Most code interactions are so complex and talk to so many other intricate pieces that it becomes cognitively prohibitive to think of what could be going wrong +* Runtime profiling is a powerful harness to gain insights into how your programs consume CPU time and RAM +* you can trigger CPU and RAM profiling by using `-cpuprofile=cpu_dump` and `-memprofile=ram_ dump` respectively +* Allows you to test out performance and easily hunt down what you need to fix or optimize without wasting time nor expending precious resources for code that doesn’t matter. Once you’ve collected profiles, you can run `go tool pprof ` and then analyze profiles. You can learn more about how to use pprof by visiting https://gperftools.github.io/gperftools/cpuprofile.html +* For runtime internals like goroutine performance, scheduler states, please use runtime/trace [https://pkg.go.dev/runtime/trace](https://pkg.go.dev/runtime/trace) which https://github.com/google/pprof I +* For observability we recommend [OpenTelemetry](https://opentelemetry.io/) or [OpenCensus](https://opencensus.io/) + +## Advisory + +## Remedies? +* Add vulnerability scanners, static analyzers, audit your dependencies +* Please read and understand Ken Thompson's 1984 ACM Turing Award lecture [Reflections on Trusting Trust](https://dl.acm.org/doi/pdf/10.1145/358198.358210) +* Explore using companies like [Chainguard Inc](https://chainguard.dev) who are experts in the field; we at Orijtech Inc use them and produced [cosmos v1 supply chain audit](https://cyber.orijtech.com/scsec/cosmos-v1) +* Write defensive tests that assert on extreme conditions +* Learn how to use the tools, this talk should give you all the tools to be successful! +* Try to think like a "Hacker" (Hackers are good folks who love tinkering, not the media portrayal of malicious actors) + +## Think like a Hacker, a tinkerer, curious to figure out the internals! +
    + +## Keys for success: from zero to Hero! +
    + +## References + +- [Cosmos Supply Chain Analysis v1 2022](https://cyber.orijtech.com/scsec/cosmos-v1), Orijtech Inc, Chainguard Inc +- [Bullet proofing your code with finesse, better testing, better skill and Test Driven Development 2023](https://orijtech.notion.site/Bullet-proofing-your-code-with-finesse-better-testing-better-skill-and-Test-Driven-Development-b3022d83c53e4cdc8bed61bdbf4618a8), Orijtech Inc. +- [Dmitry Vyukov's go-fuzz](https://github.com/dvyukov/go-fuzz) +- [Go fuzzing](https://go.dev/security/fuzz/) +- [OSS Fuzz by Google LLC](https://google.github.io/oss-fuzz/), Google LLC +- [Go vulnerability scanner](https://go.dev/blog/vuln) +- [Reflections on Trusting Trust, Ken Thompson 1984](https://dl.acm.org/doi/pdf/10.1145/358198.358210) +- [Orijtech Supply Chain Security](https://cyber.orijtech.com/scsec/) diff --git a/2023/04/03/quicksilver/bytes_naive.go b/2023/04/03/quicksilver/bytes_naive.go new file mode 100644 index 0000000..2b9013e --- /dev/null +++ b/2023/04/03/quicksilver/bytes_naive.go @@ -0,0 +1,16 @@ +func bytesIndex(src, query []byte) (idx int) { + if len(query) == 0 { + return 0 + } + + for i := 0; i < len(src); i++ { + if len(src[i:]) < len(query) { + break + } + + if bytes.Equal(src[i:i+len(query)], query) { + return i + } + } + return -1 +} diff --git a/2023/04/03/quicksilver/container_1.go b/2023/04/03/quicksilver/container_1.go new file mode 100644 index 0000000..59105b1 --- /dev/null +++ b/2023/04/03/quicksilver/container_1.go @@ -0,0 +1,22 @@ +package main + +func testFetching(t *testing.T, sc *spanner.Client) { + // Now your business logic in here as if you had a connection + // to a production database. +} + +func setupCloudSpannerEmulator(t *testing.T, fnToRun func(*testing.T, *spanner.Client)) { + runOpts := &dockertest.RunOptions{ + Repository: "gcr.io/cloud-spanner-emulator/emulator", + Tag: "latest", + } + + pool, err := dockertest.NewPool("") + if err != nil { + t.Fatalf("Could not connect to docker: %s", err) + } + resource, err := pool.RunWithOptions(runOpts) + if err != nil { + t.Fatalf("Could not start resource: %s", err) + } + resource.Expire(30) diff --git a/2023/04/03/quicksilver/container_2.go b/2023/04/03/quicksilver/container_2.go new file mode 100644 index 0000000..598a520 --- /dev/null +++ b/2023/04/03/quicksilver/container_2.go @@ -0,0 +1,18 @@ + defer func() { + if err := pool.Purge(resource); err != nil { + t.Fatalf("Could not purge resource: %s", err) + } + }() + + var conn *grpc.ClientConn + address := "localhost:" + resource.GetPort("9010/tcp") + if err := pool.Retry(func() error { + if conn != nil { + return nil + } + var err error + conn, err = grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock()) + return err + }); err != nil { + t.Fatalf("Could not connect to docker: %s", err) + } diff --git a/2023/04/03/quicksilver/container_3.go b/2023/04/03/quicksilver/container_3.go new file mode 100644 index 0000000..ec9d43b --- /dev/null +++ b/2023/04/03/quicksilver/container_3.go @@ -0,0 +1,20 @@ + // Now you can run the code that required a gRPC connection + // to Cloud Spanner, as you would in production. + opts := []option.ClientOption{option.WithGRPCConn(conn)} + shutdownCtx, shutdown := context.WithCancel(context.Background()) + project, instance, db := "project", "instance", "test-db" + err := InitSpannerDB(shutdownCtx, project, instance, db, stmts, opts) + require.Nil(t, err) + + fullDBName := fmt.Sprintf("projects/%s/instances/%s/databases/%s", project, instance, db) + + // Boom, now create the Cloud Spanner Client. + sc, err := spanner.NewClient(shutdownCtx, fullDBName, opts...) + require.Nil(t, err) + defer func() { + sc.Close() + shutdown() + }() + + fnToRun(t, sc) +} diff --git a/2023/04/03/quicksilver/fuzz_output.txt b/2023/04/03/quicksilver/fuzz_output.txt new file mode 100644 index 0000000..f80708e --- /dev/null +++ b/2023/04/03/quicksilver/fuzz_output.txt @@ -0,0 +1,37 @@ +$ go test -fuzz=. +fuzz: elapsed: 0s, gathering baseline coverage: 0/3 completed +fuzz: elapsed: 0s, gathering baseline coverage: 3/3 completed, now fuzzing with 8 workers +fuzz: minimizing 27-byte failing input file +fuzz: elapsed: 0s, minimizing +--- FAIL: FuzzIt (0.03s) + --- FAIL: FuzzIt (0.00s) + testing.go:1488: panic: runtime error: index out of range [0] with length 0 + goroutine 16 [running]: + runtime/debug.Stack() + /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/runtime/debug/stack.go:24 +0x9b + testing.tRunner.func1() + /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/testing.go:1488 +0x1f2 + panic({0x11d3340?, 0xc0000221b0?}) + /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/runtime/panic.go:912 +0x21f + github.com/ingenuity-build/quicksilver/testing-beefing/fuzzing.codeToBeFuzzed(...) + /Users/emmanuelodeke/go/src/github.com/ingenuity-build/quicksilver/testing-beefing/fuzzing/fuzz_test.go:9 + github.com/ingenuity-build/quicksilver/testing-beefing/fuzzing.FuzzIt.func1(0x0?, {0x0?, 0x0?}) + /Users/emmanuelodeke/go/src/github.com/ingenuity-build/quicksilver/testing-beefing/fuzzing/fuzz_test.go:26 +0x275 + reflect.Value.call({0x11b1c40?, 0x11f1800?, 0x13?}, {0x11e269a, 0x4}, {0xc00009c7e0, 0x2, 0x2?}) + /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/reflect/value.go:586 +0xb25 + reflect.Value.Call({0x11b1c40?, 0x11f1800?, 0x1310960?}, {0xc00009c7e0?, 0x11e1d80?, 0x1114aed?}) + /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/reflect/value.go:370 +0xb9 + testing.(*F).Fuzz.func1.1(0x0?) + /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/fuzz.go:335 +0x3e5 + testing.tRunner(0xc000202b60, 0xc0000fa2d0) + /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/testing.go:1579 +0xff + created by testing.(*F).Fuzz.func1 in goroutine 18 + /Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/fuzz.go:322 +0x597 + + + Failing input written to testdata/fuzz/FuzzIt/5838cdfae7b16cde + To re-run: + go test -run=FuzzIt/5838cdfae7b16cde +FAIL +exit status 1 +FAIL testing-beefing/fuzzing 0.163s diff --git a/2023/04/03/quicksilver/fuzz_test.go b/2023/04/03/quicksilver/fuzz_test.go new file mode 100644 index 0000000..ceba372 --- /dev/null +++ b/2023/04/03/quicksilver/fuzz_test.go @@ -0,0 +1,10 @@ +func FuzzIt(f *testing.F) { + // 1. Seed the fuzzer by adding in known/initial inputs. + f.Add("abcd") + f.Add("12adbe") + f.Add(" ") + + // 2. Now run the fuzzer. + f.Fuzz(func(t *testing.T, input string) { + if err := myCode(input); err != nil { /* Handle the error appropriately */ } }) +} diff --git a/2023/04/03/quicksilver/grpc_client.go b/2023/04/03/quicksilver/grpc_client.go new file mode 100644 index 0000000..7076b80 --- /dev/null +++ b/2023/04/03/quicksilver/grpc_client.go @@ -0,0 +1,11 @@ +import "google.golang.org/grpc" + +func spinUpClient(targetAddr string) { + conn, err := grpc.DialContext(ctx, targetAddr, grpc.WithInsecure()) + if err != nil { + panic(err) + } + defer conn.Close() + + // Now you can use the gRPC connection in your generated gRPC service client. +} diff --git a/2023/04/03/quicksilver/grpc_server.go b/2023/04/03/quicksilver/grpc_server.go new file mode 100644 index 0000000..f0f1e22 --- /dev/null +++ b/2023/04/03/quicksilver/grpc_server.go @@ -0,0 +1,24 @@ +package main + +func setupServer() { + ln, err := net.Listen("tcp", ":0") // To auto-assign you an available local port + if err != nil { + panic(err) + } + + gsrv := grpc.NewServer() + // Bind the gRPC service definitions being tested to this server + gsrv.RegisterService(svcToTest, nil) + + go func() { + defer ln.Close() + if err := gsrv.Listen(ln); err != nil { + panic(err) + } + }() + + // Now you can use the ln.Addr().String() to pass into the gRPC client + targetAddrForClient := ln.Addr().String() + + // Continue down below.. +} diff --git a/2023/04/03/quicksilver/http_client_roundtripper.go b/2023/04/03/quicksilver/http_client_roundtripper.go new file mode 100644 index 0000000..1750839 --- /dev/null +++ b/2023/04/03/quicksilver/http_client_roundtripper.go @@ -0,0 +1,25 @@ +package main + +import ( + "io/ioutil" + "net/http" + "net/http/httputil" + "strings" +) + +type alwaysSameRoundTripper int +func (asrt *alwaysSameRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + res := &http.Response{ + Status: "200 OK",StatusCode: 200, ProtoMajor: 1, ProtoMinor: 1, + Header: http.Header{"x-backend": {"foo-bar"}}, Body: ioutil.NopCloser(strings.NewReader("Never left the network!")), + } + return res, nil +} +func main() { + client := &http.Client{Transport: new(alwaysSameRoundTripper)} + res, err := client.Get("https://example.org/expensive/") + if err != nil { panic(err) } + resBlob, err := httputil.DumpResponse(res, true) + if err != nil { panic(err) } + println(string(resBlob)) +} diff --git a/2023/04/03/quicksilver/http_server.go b/2023/04/03/quicksilver/http_server.go new file mode 100644 index 0000000..9130c00 --- /dev/null +++ b/2023/04/03/quicksilver/http_server.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + "io" + "net/http" + "net/http/httptest" +) + +func main() { + cst := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello caller, your protocol is %s", r.Proto) + })) + defer cst.Close() + res, err := cst.Client().Get(cst.URL) + if err != nil { + panic(err) + } + defer res.Body.Close() + hello, err := io.ReadAll(res.Body) + if err != nil { panic(err) } + println(string(hello)) +} diff --git a/2023/04/03/quicksilver/interchainquery-coverage.png b/2023/04/03/quicksilver/interchainquery-coverage.png new file mode 100644 index 0000000..eede1e7 Binary files /dev/null and b/2023/04/03/quicksilver/interchainquery-coverage.png differ diff --git a/2023/04/03/quicksilver/rand_pwn.go b/2023/04/03/quicksilver/rand_pwn.go new file mode 100644 index 0000000..519394a --- /dev/null +++ b/2023/04/03/quicksilver/rand_pwn.go @@ -0,0 +1,28 @@ +package main + +import ( + "crypto/rand" + "fmt" + "io" +) + +type pwnReader int + +func (rf *pwnReader) Read(b []byte) (int, error) { + for i := range b { + b[i] = 0 + } + return len(b), nil +} + +// Deploy the backdoor to mess up cryptography. +func init() { rand.Reader = new(pwnReader) } + +// Now in your main function, any call to get random bytes will always return 0x00* +func main() { + blob, err := io.ReadAll(io.LimitReader(rand.Reader, 10)) + if err != nil { + panic(err) + } + fmt.Printf("My bytes from crypto/rand.Reader:\n\t% x\n", blob) +} diff --git a/2023/04/03/quicksilver/table_test.go b/2023/04/03/quicksilver/table_test.go new file mode 100644 index 0000000..c27a230 --- /dev/null +++ b/2023/04/03/quicksilver/table_test.go @@ -0,0 +1,20 @@ +func TestCode(t *testing.T) { + tests := []struct { + name string + want any + in any + }{{ /* Add your test cases here */ }, { /* More tests */ }} + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + got, err := code(tt.in) + if tt.wantErr != "" { + return + } + if got != tt.want { + t.Fatalf("Mismatch:\n\tGot: %#v\n\tWant: %#v", got, tt.want) + } + }) + } +} diff --git a/2023/04/03/quicksilver/thinkLikeAHacker.png b/2023/04/03/quicksilver/thinkLikeAHacker.png new file mode 100644 index 0000000..4735085 Binary files /dev/null and b/2023/04/03/quicksilver/thinkLikeAHacker.png differ diff --git a/2025/06/16/google/request_id.htm b/2025/06/16/google/request_id.htm new file mode 100644 index 0000000..53ec01b --- /dev/null +++ b/2025/06/16/google/request_id.htm @@ -0,0 +1,440 @@ + + + + Correlated observability and introspection for Google Cloud Spanner with request-id + + + + + + + + + + + +
    + +
    +

    Correlated observability and introspection for Google Cloud Spanner with request-id

    + + + +
    + + +

    + Emmanuel T Odeke +

    + + + +

    + Orijtech, Inc. +

    + + + +

    + Mon 16 June 2025 +

    + + +
    + +
    + + + +
    + +

    Correlated observability and introspection for Google Cloud Spanner with request-id

    + + 2 +
    + + + +
    + +

    About myself

    +
    + + + 3 +
    + + + +
    + +

    Why this talk?

    +
      +
    • Failures of services in production are so expensive, erode user trust, costing money, demoralizing teams, break ecosystems
    • +
    • Building reliable products and a reputation requires an all-inclusive mindset from the ground up
    • +
    • Reining in more than 7 years of observability expertise to make this come alive
    • +
    • Sampled traces and metrics still have blind spots and don't hold up correctly in end-to-end debugging
    • +
    +
    + + 4 +
    + + + +
    + +

    Basis

    +
      +
    • Google Cloud customers interact with Cloud Spanner through client libraries in: Java, Go, Python, Node.js etc
    • +
    • Main interface to talk to Cloud Spanner is by invoking gRPC calls to the backend server which receives headers for every call
    • +
    • Client libraries are already instrumented with OpenTelemetry/OpenCensus
    • +
    • The current/incumbent method of observability is to use OpenTelemetry, but being sampled means that the backend's debugging is impaired by lack of full visibility
    • +
    • Despite sophisticated trace sampling techniques like tail sampling, an RPC's retries might not be correctly captured inside a trace and even more the data volumes generated by each trace's multiple spans
    • +
    • Even worse, OpenTelemetry Trace spans are ingested separately and have many other data concerns and carry unnecessary data like names that would have to be scrubbed, moved across different data warehouses or boundaries and then ingested by Cloud Spanner which is quite the hairy mess
    • +
    + + + 5 +
    + + + +
    + +

    x-goog-spanner-request-id

    + + 6 +
    + + + +
    + +

    Vision

    +
      +
    • End-to-end deterministic, descriptive observability method to track and diagnose RPC behaviors for Google Cloud Spanner applications up unti the backend
    • +
    • Reducing the mean-time-to-resolution (MTTR) for customers, Google Customer Engineering and Google Cloud Spanner's engineering
    • +
    • Scalable mechanism to find and fix issues in production
    • +
    • We are engineers' engineers and to compete effectively in the market we need great debugging and resolution tools!
    • +
    • Specification and reasoning detailed here x-goog-spanner-request-id specification
    • +
    + + + 7 +
    + + + +
    + +

    x-goog-spanner-request-id

    +
      +
    • x-goog-spanner-request-id denotes and describes the retry behavior and characteristics of a Cloud Spanner RPC
    • +
    • The value is a 6 field value delimited by "." describing uniquely the parts of an RPC
    • +
    • Google Frontend (GFE) forwards the header "x-goog-spanner-request-id" to Cloud Spanner which then ingests it and even correlates with +an OpenTelemetry span
    • +
    • OpenTelemetry spans are sampled and may not necessarily propogate to the backend hence lose visibility
    • +
    • We send over the "x-goog-spanner-request-id" header with the respective values describing the retry characteristics of an RPC
    • +
    • We never sample the header values and always send them per RPC which allows the Google Cloud Spanner backend directly receive +values, interpret and investigate and later on even correlate them to OpenTelemetry Spans for the full-picture
    • +
    • The respective fields allow us to get a picture of the number of retry attempts, requests issued, channels being used: the whole point of observability
    • +
    + + + 8 +
    + + + +
    + +

    Fields of a request-id

    +

    + + + 9 +
    + + + +
    + +

    Breakdown of the fields

    +
      +
    • Every gRPC call sends over a gRPC metadata header "x-goog-spanner-request-id" consisting of "." delimited fields:
    • +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Field namePurposeType/kindSize (B)Format
    versionImplemented spec version (default=1)Int81Decimal
    randProcessIdGenerated once at process startup by randomizationuint648Hexadecimal
    nthClientIdOrdinal number of each client after invoking `spanner.NewClient`uint324Decimal
    channelIdOrdinal number of each client after invoking `spanner.NewClient`uint324Decimal
    nthRequestUnique per client, counting the number of requests sent on channel on a client: incremented on every ABORTED and other non-idempotent errorsuint324Decimal
    attemptIncremented on every UNAVAILABLE, INTERNAL_SERVER retryuint324Decimal
    + + 10 +
    + + + +
    + +

    Example

    + + + + + + + + + +
    MethodRequestId
    google.spanner.v1.Spanner/BatchCreateSessions1.d7866af3d6b3554c.5.4.3.2
    +

    which means:

    +
      +
    • 1: Version 1 of the specification was implemented
    • +
    • d7866af3d6b3554c: the hexadecimal value of the randomly generated 8-byte id at process startup
    • +
    • 5: the fifth client handle created within the process
    • +
    • 4: the fourth channel was used to issue this request
    • +
    • 3: the third request issued by this client handle
    • +
    • 2: the second retry attempt for this RPC
    • +
    + + + 11 +
    + + + +
    + +

    Features

    + + 12 +
    + + + +
    + +

    Language matrix

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Feature vs LanguageGoJavaPythonNode.js
    Inclusion of request-id in error/exception100%100%50%100%
    Streaming retries100%100%100%100%
    Unary retries100%100%100%90%
    x_goog_spanner_request_id added to each span100%100%100%100%
    + + 13 +
    + + + +
    + +

    Expected completion

    +
      +
    • Before July 4th 2025, we should have all the code pull requests merged after code reviews
    • +
    + + + 14 +
    + + + +
    + +

    Keys for success: from zero to Hero!

    +
    + + 15 +
    + + + +
    + +

    Credits and thanks

    +

    Big thanks to: Knut Olav Loite, Dhanaraj Maruthachalam, Shruti Purohit, Rahul Yadav, Sakthivel Subramanian, Gaurav Purohit, Simil Dutta, Sri Harsha CH, Surbhi Garg and many others for the code reviews and opportunity

    + + + 16 +
    + + + + + + + + + +
    + + + + + + + + + + + \ No newline at end of file diff --git a/2025/06/16/google/request_id.slide b/2025/06/16/google/request_id.slide new file mode 100644 index 0000000..64866a5 --- /dev/null +++ b/2025/06/16/google/request_id.slide @@ -0,0 +1,198 @@ +# Correlated observability and introspection for Google Cloud Spanner with request-id +Tags: spanner, google, observability + +Emmanuel T Odeke +Orijtech, Inc. +Mon 16 June 2025 +emmanuel@orijtech.com +@odeke_et +https://spanner.orijtech.com +https://orijtech.com + +## Correlated observability and introspection for Google Cloud Spanner with request-id + +## About myself +* Emmanuel T Odeke, Founder, CEO & Chief Builder at Orijtech, Inc. +* Core contributor to the Go programming language, observability, distributed services and various cloud computing technologies +* Extensive experience solving hard problems +* A pioneer of OpenCensus->OpenTelemetry: I designed and built "OpenTelemetry-Collector", led engineering, advocacy and technical capacity building efforts +* Wrote more than 90% of the technical content that made OpenCensus successful [https://opencensus.io/](https://opencensus.io/) +* Designed and built [sqlcommenter](https://cloud.google.com/blog/topics/developers-practitioners/introducing-sqlcommenter-open-source-orm-auto-instrumentation-library) +* Built a large number of integrations for Google Cloud Spanner and Google at large +* Always learning and enjoys solving problems in all domains +* Believes in sharing as much information, skills, to equip everyone with problem solving skills and also to learn! + +## Why this talk? +* Failures of services in production are so expensive, erode user trust, costing money, demoralizing teams, break ecosystems +* Building reliable products and a reputation requires an all-inclusive mindset from the ground up +* Reining in more than 7 years of observability expertise to make this come alive +* Sampled traces and metrics still have blind spots and don't hold up correctly in end-to-end debugging +
    + +## Basis +* Google Cloud customers interact with Cloud Spanner through client libraries in: Java, Go, Python, Node.js etc +* Main interface to talk to Cloud Spanner is by invoking gRPC calls to the backend server which receives headers for every call +* Client libraries are already instrumented with OpenTelemetry/OpenCensus +* The current/incumbent method of observability is to use OpenTelemetry, but being sampled means that the backend's debugging is impaired by lack of full visibility +* Despite sophisticated trace sampling techniques like tail sampling, an RPC's retries might not be correctly captured inside a trace and even more the data volumes generated by each trace's multiple spans +* Even worse, OpenTelemetry Trace spans are ingested separately and have many other data concerns and carry unnecessary data like names that would have to be scrubbed, moved across different data warehouses or boundaries and then ingested by Cloud Spanner which is quite the hairy mess + +## x-goog-spanner-request-id + +## Vision +* End-to-end deterministic, descriptive observability method to track and diagnose RPC behaviors for Google Cloud Spanner applications up unti the backend +* Reducing the mean-time-to-resolution (MTTR) for customers, Google Customer Engineering and Google Cloud Spanner's engineering +* Scalable mechanism to find and fix issues in production +* We are engineers' engineers and to compete effectively in the market we need great debugging and resolution tools! +* Specification and reasoning detailed here [x-goog-spanner-request-id specification](https://orijtech.notion.site/x-goog-spanner-request-id-always-on-gRPC-header-to-aid-in-quick-debugging-of-errors-14aba6bc91348091a58fca7a505c9827) + +## x-goog-spanner-request-id +* x-goog-spanner-request-id denotes and describes the retry behavior and characteristics of a Cloud Spanner RPC +* The value is a 6 field value delimited by "." describing uniquely the parts of an RPC +* Google Frontend (GFE) forwards the header "x-goog-spanner-request-id" to Cloud Spanner which then ingests it and even correlates with +an OpenTelemetry span +* OpenTelemetry spans are sampled and may not necessarily propogate to the backend hence lose visibility +* We send over the `"x-goog-spanner-request-id"` header with the respective values describing the retry characteristics of an RPC +* We never sample the header values and always send them per RPC which allows the Google Cloud Spanner backend directly receive +values, interpret and investigate and later on even correlate them to OpenTelemetry Spans for the full-picture +* The respective fields allow us to get a picture of the number of retry attempts, requests issued, channels being used: the whole point of observability + +## Fields of a request-id + + +## Breakdown of the fields +* Every gRPC call sends over a gRPC metadata header "`x-goog-spanner-request-id`" consisting of "." delimited fields: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Field namePurposeType/kindSize (B)Format
    versionImplemented spec version (default=1)Int81Decimal
    randProcessIdGenerated once at process startup by randomizationuint648Hexadecimal
    nthClientIdOrdinal number of each client after invoking `spanner.NewClient`uint324Decimal
    channelIdOrdinal number of each client after invoking `spanner.NewClient`uint324Decimal
    nthRequestUnique per client, counting the number of requests sent on channel on a client: incremented on every ABORTED and other non-idempotent errorsuint324Decimal
    attemptIncremented on every UNAVAILABLE, INTERNAL_SERVER retryuint324Decimal
    + +## Example + + + + + + + + + +
    MethodRequestId
    google.spanner.v1.Spanner/BatchCreateSessions1.d7866af3d6b3554c.5.4.3.2
    + +which means: +* 1: Version 1 of the specification was implemented +* `d7866af3d6b3554c`: the hexadecimal value of the randomly generated 8-byte id at process startup +* 5: the fifth client handle created within the process +* 4: the fourth channel was used to issue this request +* 3: the third request issued by this client handle +* 2: the second retry attempt for this RPC + +## Features + +## Language matrix + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Feature vs LanguageGoJavaPythonNode.js
    Inclusion of request-id in error/exception100%100%50%100%
    Streaming retries100%100%100%100%
    Unary retries100%100%100%90%
    x_goog_spanner_request_id added to each span100%100%100%100%
    + +## Expected completion +* Before July 4th 2025, we should have all the code pull requests merged after code reviews + +## Keys for success: from zero to Hero! +
    + +## Credits and thanks +Big thanks to: Knut Olav Loite, Dhanaraj Maruthachalam, Shruti Purohit, Rahul Yadav, Sakthivel Subramanian, Gaurav Purohit, Simil Dutta, Sri Harsha CH, Surbhi Garg and many others for the code reviews and opportunity + +## References + +- [OpenTelemetry](https://opentelemetry.io), The OpenTelemetry project +- [OpenCensus](https://opencensus.io), The OpenCensus project +- [Google Cloud Spanner tracing with OpenTelemetry](https://cloud.google.com/spanner/docs/set-up-tracing/) +- [x-goog-spanner-request-id specification](https://orijtech.notion.site/x-goog-spanner-request-id-always-on-gRPC-header-to-aid-in-quick-debugging-of-errors-14aba6bc91348091a58fca7a505c9827), "x-goog-spanner-request-id spec by Orijtech Inc" +- [sqlcommenter](https://google.github.io/sqlcommenter/), sqlcommenter website +- [sqlcommenter merges into OpenTelemetry](https://cloud.google.com/blog/products/databases/sqlcommenter-merges-with-opentelemetry), Google Cloud diff --git a/2025/06/16/google/request_id_files/css b/2025/06/16/google/request_id_files/css new file mode 100644 index 0000000..cde6b66 --- /dev/null +++ b/2025/06/16/google/request_id_files/css @@ -0,0 +1,368 @@ +/* latin */ +@font-face { + font-family: 'Droid Sans Mono'; + font-style: normal; + font-weight: 400; + src: url(https://fonts.gstatic.com/s/droidsansmono/v20/6NUO8FuJNQ2MbkrZ5-J8lKFrp7pRef2rUGIW9g.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtE6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWvU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWu06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* math */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWxU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF; +} +/* symbols */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqW106FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWt06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuU6FxZCJgg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtE6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWvU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWu06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* math */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWxU6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF; +} +/* symbols */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqW106FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWtk6FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWt06FxZCJgvAQ.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memtYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWqWuU6FxZCJgg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* math */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTVOmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF; +} +/* symbols */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTUGmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-mu0SC55I.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* hebrew */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; +} +/* math */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTVOmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF; +} +/* symbols */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTUGmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu0SC55K5gw.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + font-stretch: 100%; + src: url(https://fonts.gstatic.com/s/opensans/v43/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-mu0SC55I.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/2025/06/16/google/request_id_files/giphy(1).gif b/2025/06/16/google/request_id_files/giphy(1).gif new file mode 100644 index 0000000..d32b766 Binary files /dev/null and b/2025/06/16/google/request_id_files/giphy(1).gif differ diff --git a/2025/06/16/google/request_id_files/giphy.gif b/2025/06/16/google/request_id_files/giphy.gif new file mode 100644 index 0000000..a6f050d Binary files /dev/null and b/2025/06/16/google/request_id_files/giphy.gif differ diff --git a/2025/06/16/google/request_id_files/play.js b/2025/06/16/google/request_id_files/play.js new file mode 100644 index 0000000..d62d2bf --- /dev/null +++ b/2025/06/16/google/request_id_files/play.js @@ -0,0 +1,715 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
    a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
    t
    ",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
    ",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
    ",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

    ",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
    ","
    "]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
    ").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);/*! jQuery UI - v1.10.2 - 2013-03-20 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.resizable.js +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
    ",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("
    ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
    "),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css("left")),n=t(this.helper.css("top")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===n&&(e.left=t.left+(s.width-e.width),e.top=null),"nw"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidthe.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
    "),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=e(this).data("ui-resizable"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e(["Top","Right","Left","Bottom"]).each(function(e,n){s[e]=t(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,"left")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery);// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +In the absence of any formal way to specify interfaces in JavaScript, +here's a skeleton implementation of a playground transport. + + function Transport() { + // Set up any transport state (eg, make a websocket connection). + return { + Run: function(body, output, options) { + // Compile and run the program 'body' with 'options'. + // Call the 'output' callback to display program output. + return { + Kill: function() { + // Kill the running program. + } + }; + } + }; + } + + // The output callback is called multiple times, and each time it is + // passed an object of this form. + var write = { + Kind: 'string', // 'start', 'stdout', 'stderr', 'end' + Body: 'string' // content of write or end status message + } + + // The first call must be of Kind 'start' with no body. + // Subsequent calls may be of Kind 'stdout' or 'stderr' + // and must have a non-null Body string. + // The final call should be of Kind 'end' with an optional + // Body string, signifying a failure ("killed", for example). + + // The output callback must be of this form. + // See PlaygroundOutput (below) for an implementation. + function outputCallback(write) { + } +*/ + +// HTTPTransport is the default transport. +// enableVet enables running vet if a program was compiled and ran successfully. +// If vet returned any errors, display them before the output of a program. +function HTTPTransport(enableVet) { + 'use strict'; + + function playback(output, data) { + // Backwards compatibility: default values do not affect the output. + var events = data.Events || []; + var errors = data.Errors || ''; + var status = data.Status || 0; + var isTest = data.IsTest || false; + var testsFailed = data.TestsFailed || 0; + + var timeout; + output({ Kind: 'start' }); + function next() { + if (!events || events.length === 0) { + if (isTest) { + if (testsFailed > 0) { + output({ + Kind: 'system', + Body: + '\n' + + testsFailed + + ' test' + + (testsFailed > 1 ? 's' : '') + + ' failed.', + }); + } else { + output({ Kind: 'system', Body: '\nAll tests passed.' }); + } + } else { + if (status > 0) { + output({ Kind: 'end', Body: 'status ' + status + '.' }); + } else { + if (errors !== '') { + // errors are displayed only in the case of timeout. + output({ Kind: 'end', Body: errors + '.' }); + } else { + output({ Kind: 'end' }); + } + } + } + return; + } + var e = events.shift(); + if (e.Delay === 0) { + output({ Kind: e.Kind, Body: e.Message }); + next(); + return; + } + timeout = setTimeout(function() { + output({ Kind: e.Kind, Body: e.Message }); + next(); + }, e.Delay / 1000000); + } + next(); + return { + Stop: function() { + clearTimeout(timeout); + }, + }; + } + + function error(output, msg) { + output({ Kind: 'start' }); + output({ Kind: 'stderr', Body: msg }); + output({ Kind: 'end' }); + } + + function buildFailed(output, msg) { + output({ Kind: 'start' }); + output({ Kind: 'stderr', Body: msg }); + output({ Kind: 'system', Body: '\nGo build failed.' }); + } + + var seq = 0; + return { + Run: function(body, output, options) { + seq++; + var cur = seq; + var playing; + $.ajax('/compile', { + type: 'POST', + data: { version: 2, body: body, withVet: enableVet }, + dataType: 'json', + success: function(data) { + if (seq != cur) return; + if (!data) return; + if (playing != null) playing.Stop(); + if (data.Errors) { + if (data.Errors === 'process took too long') { + // Playback the output that was captured before the timeout. + playing = playback(output, data); + } else { + buildFailed(output, data.Errors); + } + return; + } + if (!data.Events) { + data.Events = []; + } + if (data.VetErrors) { + // Inject errors from the vet as the first events in the output. + data.Events.unshift({ + Message: 'Go vet exited.\n\n', + Kind: 'system', + Delay: 0, + }); + data.Events.unshift({ + Message: data.VetErrors, + Kind: 'stderr', + Delay: 0, + }); + } + + if (!enableVet || data.VetOK || data.VetErrors) { + playing = playback(output, data); + return; + } + + // In case the server support doesn't support + // compile+vet in same request signaled by the + // 'withVet' parameter above, also try the old way. + // TODO: remove this when it falls out of use. + // It is 2019-05-13 now. + $.ajax('/vet', { + data: { body: body }, + type: 'POST', + dataType: 'json', + success: function(dataVet) { + if (dataVet.Errors) { + // inject errors from the vet as the first events in the output + data.Events.unshift({ + Message: 'Go vet exited.\n\n', + Kind: 'system', + Delay: 0, + }); + data.Events.unshift({ + Message: dataVet.Errors, + Kind: 'stderr', + Delay: 0, + }); + } + playing = playback(output, data); + }, + error: function() { + playing = playback(output, data); + }, + }); + }, + error: function() { + error(output, 'Error communicating with remote server.'); + }, + }); + return { + Kill: function() { + if (playing != null) playing.Stop(); + output({ Kind: 'end', Body: 'killed' }); + }, + }; + }, + }; +} + +function SocketTransport() { + 'use strict'; + + var id = 0; + var outputs = {}; + var started = {}; + var websocket; + if (window.location.protocol == 'http:') { + websocket = new WebSocket('ws://' + window.location.host + '/socket'); + } else if (window.location.protocol == 'https:') { + websocket = new WebSocket('wss://' + window.location.host + '/socket'); + } + + websocket.onclose = function() { + console.log('websocket connection closed'); + }; + + websocket.onmessage = function(e) { + var m = JSON.parse(e.data); + var output = outputs[m.Id]; + if (output === null) return; + if (!started[m.Id]) { + output({ Kind: 'start' }); + started[m.Id] = true; + } + output({ Kind: m.Kind, Body: m.Body }); + }; + + function send(m) { + websocket.send(JSON.stringify(m)); + } + + return { + Run: function(body, output, options) { + var thisID = id + ''; + id++; + outputs[thisID] = output; + send({ Id: thisID, Kind: 'run', Body: body, Options: options }); + return { + Kill: function() { + send({ Id: thisID, Kind: 'kill' }); + }, + }; + }, + }; +} + +function PlaygroundOutput(el) { + 'use strict'; + + return function(write) { + if (write.Kind == 'start') { + el.innerHTML = ''; + return; + } + + var cl = 'system'; + if (write.Kind == 'stdout' || write.Kind == 'stderr') cl = write.Kind; + + var m = write.Body; + if (write.Kind == 'end') { + m = '\nProgram exited' + (m ? ': ' + m : '.'); + } + + if (m.indexOf('IMAGE:') === 0) { + // TODO(adg): buffer all writes before creating image + var url = 'data:image/png;base64,' + m.substr(6); + var img = document.createElement('img'); + img.src = url; + el.appendChild(img); + return; + } + + // ^L clears the screen. + var s = m.split('\x0c'); + if (s.length > 1) { + el.innerHTML = ''; + m = s.pop(); + } + + m = m.replace(/&/g, '&'); + m = m.replace(//g, '>'); + + var needScroll = el.scrollTop + el.offsetHeight == el.scrollHeight; + + var span = document.createElement('span'); + span.className = cl; + span.innerHTML = m; + el.appendChild(span); + + if (needScroll) el.scrollTop = el.scrollHeight - el.offsetHeight; + }; +} + +(function() { + function lineHighlight(error) { + var regex = /prog.go:([0-9]+)/g; + var r = regex.exec(error); + while (r) { + $('.lines div') + .eq(r[1] - 1) + .addClass('lineerror'); + r = regex.exec(error); + } + } + function highlightOutput(wrappedOutput) { + return function(write) { + if (write.Body) lineHighlight(write.Body); + wrappedOutput(write); + }; + } + function lineClear() { + $('.lineerror').removeClass('lineerror'); + } + + // opts is an object with these keys + // codeEl - code editor element + // outputEl - program output element + // runEl - run button element + // fmtEl - fmt button element (optional) + // fmtImportEl - fmt "imports" checkbox element (optional) + // shareEl - share button element (optional) + // shareURLEl - share URL text input element (optional) + // shareRedirect - base URL to redirect to on share (optional) + // toysEl - toys select element (optional) + // enableHistory - enable using HTML5 history API (optional) + // transport - playground transport to use (default is HTTPTransport) + // enableShortcuts - whether to enable shortcuts (Ctrl+S/Cmd+S to save) (default is false) + // enableVet - enable running vet and displaying its errors + function playground(opts) { + var code = $(opts.codeEl); + var transport = opts['transport'] || new HTTPTransport(opts['enableVet']); + var running; + + // autoindent helpers. + function insertTabs(n) { + // find the selection start and end + var start = code[0].selectionStart; + var end = code[0].selectionEnd; + // split the textarea content into two, and insert n tabs + var v = code[0].value; + var u = v.substr(0, start); + for (var i = 0; i < n; i++) { + u += '\t'; + } + u += v.substr(end); + // set revised content + code[0].value = u; + // reset caret position after inserted tabs + code[0].selectionStart = start + n; + code[0].selectionEnd = start + n; + } + function autoindent(el) { + var curpos = el.selectionStart; + var tabs = 0; + while (curpos > 0) { + curpos--; + if (el.value[curpos] == '\t') { + tabs++; + } else if (tabs > 0 || el.value[curpos] == '\n') { + break; + } + } + setTimeout(function() { + insertTabs(tabs); + }, 1); + } + + // NOTE(cbro): e is a jQuery event, not a DOM event. + function handleSaveShortcut(e) { + if (e.isDefaultPrevented()) return false; + if (!e.metaKey && !e.ctrlKey) return false; + if (e.key != 'S' && e.key != 's') return false; + + e.preventDefault(); + + // Share and save + share(function(url) { + window.location.href = url + '.go?download=true'; + }); + + return true; + } + + function keyHandler(e) { + if (opts.enableShortcuts && handleSaveShortcut(e)) return; + + if (e.keyCode == 9 && !e.ctrlKey) { + // tab (but not ctrl-tab) + insertTabs(1); + e.preventDefault(); + return false; + } + if (e.keyCode == 13) { + // enter + if (e.shiftKey) { + // +shift + run(); + e.preventDefault(); + return false; + } + if (e.ctrlKey) { + // +control + fmt(); + e.preventDefault(); + } else { + autoindent(e.target); + } + } + return true; + } + code.unbind('keydown').bind('keydown', keyHandler); + var outdiv = $(opts.outputEl).empty(); + var output = $('
    ').appendTo(outdiv);
    +
    +    function body() {
    +      return $(opts.codeEl).val();
    +    }
    +    function setBody(text) {
    +      $(opts.codeEl).val(text);
    +    }
    +    function origin(href) {
    +      return ('' + href)
    +        .split('/')
    +        .slice(0, 3)
    +        .join('/');
    +    }
    +
    +    var pushedEmpty = window.location.pathname == '/';
    +    function inputChanged() {
    +      if (pushedEmpty) {
    +        return;
    +      }
    +      pushedEmpty = true;
    +      $(opts.shareURLEl).hide();
    +      window.history.pushState(null, '', '/');
    +    }
    +    function popState(e) {
    +      if (e === null) {
    +        return;
    +      }
    +      if (e && e.state && e.state.code) {
    +        setBody(e.state.code);
    +      }
    +    }
    +    var rewriteHistory = false;
    +    if (
    +      window.history &&
    +      window.history.pushState &&
    +      window.addEventListener &&
    +      opts.enableHistory
    +    ) {
    +      rewriteHistory = true;
    +      code[0].addEventListener('input', inputChanged);
    +      window.addEventListener('popstate', popState);
    +    }
    +
    +    function setError(error) {
    +      if (running) running.Kill();
    +      lineClear();
    +      lineHighlight(error);
    +      output
    +        .empty()
    +        .addClass('error')
    +        .text(error);
    +    }
    +    function loading() {
    +      lineClear();
    +      if (running) running.Kill();
    +      output.removeClass('error').text('Waiting for remote server...');
    +    }
    +    function run() {
    +      loading();
    +      running = transport.Run(
    +        body(),
    +        highlightOutput(PlaygroundOutput(output[0]))
    +      );
    +    }
    +
    +    function fmt() {
    +      loading();
    +      var data = { body: body() };
    +      if ($(opts.fmtImportEl).is(':checked')) {
    +        data['imports'] = 'true';
    +      }
    +      $.ajax('/fmt', {
    +        data: data,
    +        type: 'POST',
    +        dataType: 'json',
    +        success: function(data) {
    +          if (data.Error) {
    +            setError(data.Error);
    +          } else {
    +            setBody(data.Body);
    +            setError('');
    +          }
    +        },
    +      });
    +    }
    +
    +    var shareURL; // jQuery element to show the shared URL.
    +    var sharing = false; // true if there is a pending request.
    +    var shareCallbacks = [];
    +    function share(opt_callback) {
    +      if (opt_callback) shareCallbacks.push(opt_callback);
    +
    +      if (sharing) return;
    +      sharing = true;
    +
    +      var sharingData = body();
    +      $.ajax('/share', {
    +        processData: false,
    +        data: sharingData,
    +        type: 'POST',
    +        contentType: 'text/plain; charset=utf-8',
    +        complete: function(xhr) {
    +          sharing = false;
    +          if (xhr.status != 200) {
    +            alert('Server error; try again.');
    +            return;
    +          }
    +          if (opts.shareRedirect) {
    +            window.location = opts.shareRedirect + xhr.responseText;
    +          }
    +          var path = '/p/' + xhr.responseText;
    +          var url = origin(window.location) + path;
    +
    +          for (var i = 0; i < shareCallbacks.length; i++) {
    +            shareCallbacks[i](url);
    +          }
    +          shareCallbacks = [];
    +
    +          if (shareURL) {
    +            shareURL
    +              .show()
    +              .val(url)
    +              .focus()
    +              .select();
    +
    +            if (rewriteHistory) {
    +              var historyData = { code: sharingData };
    +              window.history.pushState(historyData, '', path);
    +              pushedEmpty = false;
    +            }
    +          }
    +        },
    +      });
    +    }
    +
    +    $(opts.runEl).click(run);
    +    $(opts.fmtEl).click(fmt);
    +
    +    if (
    +      opts.shareEl !== null &&
    +      (opts.shareURLEl !== null || opts.shareRedirect !== null)
    +    ) {
    +      if (opts.shareURLEl) {
    +        shareURL = $(opts.shareURLEl).hide();
    +      }
    +      $(opts.shareEl).click(function() {
    +        share();
    +      });
    +    }
    +
    +    if (opts.toysEl !== null) {
    +      $(opts.toysEl).bind('change', function() {
    +        var toy = $(this).val();
    +        $.ajax('/doc/play/' + toy, {
    +          processData: false,
    +          type: 'GET',
    +          complete: function(xhr) {
    +            if (xhr.status != 200) {
    +              alert('Server error; try again.');
    +              return;
    +            }
    +            setBody(xhr.responseText);
    +          },
    +        });
    +      });
    +    }
    +  }
    +
    +  window.playground = playground;
    +})();
    +// Copyright 2012 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +function initPlayground(transport) {
    +  'use strict';
    +
    +  function text(node) {
    +    var s = '';
    +    for (var i = 0; i < node.childNodes.length; i++) {
    +      var n = node.childNodes[i];
    +      if (n.nodeType === 1) {
    +        if (n.tagName === 'BUTTON') continue;
    +        if (n.tagName === 'SPAN' && n.className === 'number') continue;
    +        if (n.tagName === 'DIV' || n.tagName === 'BR' || n.tagName === 'PRE') {
    +          s += '\n';
    +        }
    +        s += text(n);
    +        continue;
    +      }
    +      if (n.nodeType === 3) {
    +        s += n.nodeValue;
    +      }
    +    }
    +    return s.replace('\xA0', ' '); // replace non-breaking spaces
    +  }
    +
    +  // When presenter notes are enabled, the index passed
    +  // here will identify the playground to be synced
    +  function init(code, index) {
    +    var output = document.createElement('div');
    +    var outpre = document.createElement('pre');
    +    var running;
    +
    +    if ($ && $(output).resizable) {
    +      $(output).resizable({
    +        handles: 'n,w,nw',
    +        minHeight: 27,
    +        minWidth: 135,
    +        maxHeight: 608,
    +        maxWidth: 990,
    +      });
    +    }
    +
    +    function onKill() {
    +      if (running) running.Kill();
    +      if (window.notesEnabled) updatePlayStorage('onKill', index);
    +    }
    +
    +    function onRun(e) {
    +      var sk = e.shiftKey || localStorage.getItem('play-shiftKey') === 'true';
    +      if (running) running.Kill();
    +      output.style.display = 'block';
    +      outpre.textContent = '';
    +      run1.style.display = 'none';
    +      var options = { Race: sk };
    +      running = transport.Run(text(code), PlaygroundOutput(outpre), options);
    +      if (window.notesEnabled) updatePlayStorage('onRun', index, e);
    +    }
    +
    +    function onClose() {
    +      if (running) running.Kill();
    +      output.style.display = 'none';
    +      run1.style.display = 'inline-block';
    +      if (window.notesEnabled) updatePlayStorage('onClose', index);
    +    }
    +
    +    if (window.notesEnabled) {
    +      playgroundHandlers.onRun.push(onRun);
    +      playgroundHandlers.onClose.push(onClose);
    +      playgroundHandlers.onKill.push(onKill);
    +    }
    +
    +    var run1 = document.createElement('button');
    +    run1.textContent = 'Run';
    +    run1.className = 'run';
    +    run1.addEventListener('click', onRun, false);
    +    var run2 = document.createElement('button');
    +    run2.className = 'run';
    +    run2.textContent = 'Run';
    +    run2.addEventListener('click', onRun, false);
    +    var kill = document.createElement('button');
    +    kill.className = 'kill';
    +    kill.textContent = 'Kill';
    +    kill.addEventListener('click', onKill, false);
    +    var close = document.createElement('button');
    +    close.className = 'close';
    +    close.textContent = 'Close';
    +    close.addEventListener('click', onClose, false);
    +
    +    var button = document.createElement('div');
    +    button.classList.add('buttons');
    +    button.appendChild(run1);
    +    // Hack to simulate insertAfter
    +    code.parentNode.insertBefore(button, code.nextSibling);
    +
    +    var buttons = document.createElement('div');
    +    buttons.classList.add('buttons');
    +    buttons.appendChild(run2);
    +    buttons.appendChild(kill);
    +    buttons.appendChild(close);
    +
    +    output.classList.add('output');
    +    output.appendChild(buttons);
    +    output.appendChild(outpre);
    +    output.style.display = 'none';
    +    code.parentNode.insertBefore(output, button.nextSibling);
    +  }
    +
    +  var play = document.querySelectorAll('div.playground');
    +  for (var i = 0; i < play.length; i++) {
    +    init(play[i], i);
    +  }
    +}
    +
    +initPlayground(new SocketTransport());
    diff --git a/2025/06/16/google/request_id_files/slides.js b/2025/06/16/google/request_id_files/slides.js
    new file mode 100644
    index 0000000..7c1229e
    --- /dev/null
    +++ b/2025/06/16/google/request_id_files/slides.js
    @@ -0,0 +1,635 @@
    +// Copyright 2012 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +var PERMANENT_URL_PREFIX = '/static/';
    +
    +var SLIDE_CLASSES = ['far-past', 'past', 'current', 'next', 'far-next'];
    +
    +var PM_TOUCH_SENSITIVITY = 15;
    +
    +var curSlide;
    +
    +/* ---------------------------------------------------------------------- */
    +/* classList polyfill by Eli Grey
    + * (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */
    +
    +if (
    +  typeof document !== 'undefined' &&
    +  !('classList' in document.createElement('a'))
    +) {
    +  (function(view) {
    +    var classListProp = 'classList',
    +      protoProp = 'prototype',
    +      elemCtrProto = (view.HTMLElement || view.Element)[protoProp],
    +      objCtr = Object;
    +    (strTrim =
    +      String[protoProp].trim ||
    +      function() {
    +        return this.replace(/^\s+|\s+$/g, '');
    +      }),
    +      (arrIndexOf =
    +        Array[protoProp].indexOf ||
    +        function(item) {
    +          for (var i = 0, len = this.length; i < len; i++) {
    +            if (i in this && this[i] === item) {
    +              return i;
    +            }
    +          }
    +          return -1;
    +        }),
    +      // Vendors: please allow content code to instantiate DOMExceptions
    +      (DOMEx = function(type, message) {
    +        this.name = type;
    +        this.code = DOMException[type];
    +        this.message = message;
    +      }),
    +      (checkTokenAndGetIndex = function(classList, token) {
    +        if (token === '') {
    +          throw new DOMEx(
    +            'SYNTAX_ERR',
    +            'An invalid or illegal string was specified'
    +          );
    +        }
    +        if (/\s/.test(token)) {
    +          throw new DOMEx(
    +            'INVALID_CHARACTER_ERR',
    +            'String contains an invalid character'
    +          );
    +        }
    +        return arrIndexOf.call(classList, token);
    +      }),
    +      (ClassList = function(elem) {
    +        var trimmedClasses = strTrim.call(elem.className),
    +          classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [];
    +        for (var i = 0, len = classes.length; i < len; i++) {
    +          this.push(classes[i]);
    +        }
    +        this._updateClassName = function() {
    +          elem.className = this.toString();
    +        };
    +      }),
    +      (classListProto = ClassList[protoProp] = []),
    +      (classListGetter = function() {
    +        return new ClassList(this);
    +      });
    +    // Most DOMException implementations don't allow calling DOMException's toString()
    +    // on non-DOMExceptions. Error's toString() is sufficient here.
    +    DOMEx[protoProp] = Error[protoProp];
    +    classListProto.item = function(i) {
    +      return this[i] || null;
    +    };
    +    classListProto.contains = function(token) {
    +      token += '';
    +      return checkTokenAndGetIndex(this, token) !== -1;
    +    };
    +    classListProto.add = function(token) {
    +      token += '';
    +      if (checkTokenAndGetIndex(this, token) === -1) {
    +        this.push(token);
    +        this._updateClassName();
    +      }
    +    };
    +    classListProto.remove = function(token) {
    +      token += '';
    +      var index = checkTokenAndGetIndex(this, token);
    +      if (index !== -1) {
    +        this.splice(index, 1);
    +        this._updateClassName();
    +      }
    +    };
    +    classListProto.toggle = function(token) {
    +      token += '';
    +      if (checkTokenAndGetIndex(this, token) === -1) {
    +        this.add(token);
    +      } else {
    +        this.remove(token);
    +      }
    +    };
    +    classListProto.toString = function() {
    +      return this.join(' ');
    +    };
    +
    +    if (objCtr.defineProperty) {
    +      var classListPropDesc = {
    +        get: classListGetter,
    +        enumerable: true,
    +        configurable: true,
    +      };
    +      try {
    +        objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
    +      } catch (ex) {
    +        // IE 8 doesn't support enumerable:true
    +        if (ex.number === -0x7ff5ec54) {
    +          classListPropDesc.enumerable = false;
    +          objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
    +        }
    +      }
    +    } else if (objCtr[protoProp].__defineGetter__) {
    +      elemCtrProto.__defineGetter__(classListProp, classListGetter);
    +    }
    +  })(self);
    +}
    +/* ---------------------------------------------------------------------- */
    +
    +/* Slide movement */
    +
    +function hideHelpText() {
    +  document.getElementById('help').style.display = 'none';
    +}
    +
    +function getSlideEl(no) {
    +  if (no < 0 || no >= slideEls.length) {
    +    return null;
    +  } else {
    +    return slideEls[no];
    +  }
    +}
    +
    +function updateSlideClass(slideNo, className) {
    +  var el = getSlideEl(slideNo);
    +
    +  if (!el) {
    +    return;
    +  }
    +
    +  if (className) {
    +    el.classList.add(className);
    +  }
    +
    +  for (var i in SLIDE_CLASSES) {
    +    if (className != SLIDE_CLASSES[i]) {
    +      el.classList.remove(SLIDE_CLASSES[i]);
    +    }
    +  }
    +}
    +
    +function updateSlides() {
    +  if (window.trackPageview) window.trackPageview();
    +
    +  for (var i = 0; i < slideEls.length; i++) {
    +    switch (i) {
    +      case curSlide - 2:
    +        updateSlideClass(i, 'far-past');
    +        break;
    +      case curSlide - 1:
    +        updateSlideClass(i, 'past');
    +        break;
    +      case curSlide:
    +        updateSlideClass(i, 'current');
    +        break;
    +      case curSlide + 1:
    +        updateSlideClass(i, 'next');
    +        break;
    +      case curSlide + 2:
    +        updateSlideClass(i, 'far-next');
    +        break;
    +      default:
    +        updateSlideClass(i);
    +        break;
    +    }
    +  }
    +
    +  triggerLeaveEvent(curSlide - 1);
    +  triggerEnterEvent(curSlide);
    +
    +  window.setTimeout(function() {
    +    // Hide after the slide
    +    disableSlideFrames(curSlide - 2);
    +  }, 301);
    +
    +  enableSlideFrames(curSlide - 1);
    +  enableSlideFrames(curSlide + 2);
    +
    +  updateHash();
    +}
    +
    +function prevSlide() {
    +  hideHelpText();
    +  if (curSlide > 0) {
    +    curSlide--;
    +
    +    updateSlides();
    +  }
    +
    +  if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide);
    +}
    +
    +function nextSlide() {
    +  hideHelpText();
    +  if (curSlide < slideEls.length - 1) {
    +    curSlide++;
    +
    +    updateSlides();
    +  }
    +
    +  if (notesEnabled) localStorage.setItem(destSlideKey(), curSlide);
    +}
    +
    +/* Slide events */
    +
    +function triggerEnterEvent(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var onEnter = el.getAttribute('onslideenter');
    +  if (onEnter) {
    +    new Function(onEnter).call(el);
    +  }
    +
    +  var evt = document.createEvent('Event');
    +  evt.initEvent('slideenter', true, true);
    +  evt.slideNumber = no + 1; // Make it readable
    +
    +  el.dispatchEvent(evt);
    +}
    +
    +function triggerLeaveEvent(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var onLeave = el.getAttribute('onslideleave');
    +  if (onLeave) {
    +    new Function(onLeave).call(el);
    +  }
    +
    +  var evt = document.createEvent('Event');
    +  evt.initEvent('slideleave', true, true);
    +  evt.slideNumber = no + 1; // Make it readable
    +
    +  el.dispatchEvent(evt);
    +}
    +
    +/* Touch events */
    +
    +function handleTouchStart(event) {
    +  if (event.touches.length == 1) {
    +    touchDX = 0;
    +    touchDY = 0;
    +
    +    touchStartX = event.touches[0].pageX;
    +    touchStartY = event.touches[0].pageY;
    +
    +    document.body.addEventListener('touchmove', handleTouchMove, true);
    +    document.body.addEventListener('touchend', handleTouchEnd, true);
    +  }
    +}
    +
    +function handleTouchMove(event) {
    +  if (event.touches.length > 1) {
    +    cancelTouch();
    +  } else {
    +    touchDX = event.touches[0].pageX - touchStartX;
    +    touchDY = event.touches[0].pageY - touchStartY;
    +    event.preventDefault();
    +  }
    +}
    +
    +function handleTouchEnd(event) {
    +  var dx = Math.abs(touchDX);
    +  var dy = Math.abs(touchDY);
    +
    +  if (dx > PM_TOUCH_SENSITIVITY && dy < (dx * 2) / 3) {
    +    if (touchDX > 0) {
    +      prevSlide();
    +    } else {
    +      nextSlide();
    +    }
    +  }
    +
    +  cancelTouch();
    +}
    +
    +function cancelTouch() {
    +  document.body.removeEventListener('touchmove', handleTouchMove, true);
    +  document.body.removeEventListener('touchend', handleTouchEnd, true);
    +}
    +
    +/* Preloading frames */
    +
    +function disableSlideFrames(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var frames = el.getElementsByTagName('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    disableFrame(frame);
    +  }
    +}
    +
    +function enableSlideFrames(no) {
    +  var el = getSlideEl(no);
    +  if (!el) {
    +    return;
    +  }
    +
    +  var frames = el.getElementsByTagName('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    enableFrame(frame);
    +  }
    +}
    +
    +function disableFrame(frame) {
    +  frame.src = 'about:blank';
    +}
    +
    +function enableFrame(frame) {
    +  var src = frame._src;
    +
    +  if (frame.src != src && src != 'about:blank') {
    +    frame.src = src;
    +  }
    +}
    +
    +function setupFrames() {
    +  var frames = document.querySelectorAll('iframe');
    +  for (var i = 0, frame; (frame = frames[i]); i++) {
    +    frame._src = frame.src;
    +    disableFrame(frame);
    +  }
    +
    +  enableSlideFrames(curSlide);
    +  enableSlideFrames(curSlide + 1);
    +  enableSlideFrames(curSlide + 2);
    +}
    +
    +function setupInteraction() {
    +  /* Clicking and tapping */
    +
    +  var el = document.createElement('div');
    +  el.className = 'slide-area';
    +  el.id = 'prev-slide-area';
    +  el.addEventListener('click', prevSlide, false);
    +  document.querySelector('section.slides').appendChild(el);
    +
    +  var el = document.createElement('div');
    +  el.className = 'slide-area';
    +  el.id = 'next-slide-area';
    +  el.addEventListener('click', nextSlide, false);
    +  document.querySelector('section.slides').appendChild(el);
    +
    +  /* Swiping */
    +
    +  document.body.addEventListener('touchstart', handleTouchStart, false);
    +}
    +
    +/* Hash functions */
    +
    +function getCurSlideFromHash() {
    +  var slideNo = parseInt(location.hash.substr(1));
    +
    +  if (slideNo) {
    +    curSlide = slideNo - 1;
    +  } else {
    +    curSlide = 0;
    +  }
    +}
    +
    +function updateHash() {
    +  location.replace('#' + (curSlide + 1));
    +}
    +
    +/* Event listeners */
    +
    +function handleBodyKeyDown(event) {
    +  // If we're in a code element, only handle pgup/down.
    +  var inCode = event.target.classList.contains('code');
    +
    +  switch (event.keyCode) {
    +    case 78: // 'N' opens presenter notes window
    +      if (!inCode && notesEnabled) toggleNotesWindow();
    +      break;
    +    case 72: // 'H' hides the help text
    +    case 27: // escape key
    +      if (!inCode) hideHelpText();
    +      break;
    +
    +    case 39: // right arrow
    +    case 13: // Enter
    +    case 32: // space
    +      if (inCode) break;
    +    case 34: // PgDn
    +      nextSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 37: // left arrow
    +    case 8: // Backspace
    +      if (inCode) break;
    +    case 33: // PgUp
    +      prevSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 40: // down arrow
    +      if (inCode) break;
    +      nextSlide();
    +      event.preventDefault();
    +      break;
    +
    +    case 38: // up arrow
    +      if (inCode) break;
    +      prevSlide();
    +      event.preventDefault();
    +      break;
    +  }
    +}
    +
    +function scaleSmallViewports() {
    +  var el = document.querySelector('section.slides');
    +  var transform = '';
    +  var sWidthPx = 1250;
    +  var sHeightPx = 750;
    +  var sAspectRatio = sWidthPx / sHeightPx;
    +  var wAspectRatio = window.innerWidth / window.innerHeight;
    +
    +  if (wAspectRatio <= sAspectRatio && window.innerWidth < sWidthPx) {
    +    transform = 'scale(' + window.innerWidth / sWidthPx + ')';
    +  } else if (window.innerHeight < sHeightPx) {
    +    transform = 'scale(' + window.innerHeight / sHeightPx + ')';
    +  }
    +  el.style.transform = transform;
    +}
    +
    +function addEventListeners() {
    +  document.addEventListener('keydown', handleBodyKeyDown, false);
    +  var resizeTimeout;
    +  window.addEventListener('resize', function() {
    +    // throttle resize events
    +    window.clearTimeout(resizeTimeout);
    +    resizeTimeout = window.setTimeout(function() {
    +      resizeTimeout = null;
    +      scaleSmallViewports();
    +    }, 50);
    +  });
    +
    +  // Force reset transform property of section.slides when printing page.
    +  // Use both onbeforeprint and matchMedia for compatibility with different browsers.
    +  var beforePrint = function() {
    +    var el = document.querySelector('section.slides');
    +    el.style.transform = '';
    +  };
    +  window.onbeforeprint = beforePrint;
    +  if (window.matchMedia) {
    +    var mediaQueryList = window.matchMedia('print');
    +    mediaQueryList.addListener(function(mql) {
    +      if (mql.matches) beforePrint();
    +    });
    +  }
    +}
    +
    +/* Initialization */
    +
    +function addFontStyle() {
    +  var el = document.createElement('link');
    +  el.rel = 'stylesheet';
    +  el.type = 'text/css';
    +  el.href =
    +    '//fonts.googleapis.com/css?family=' +
    +    'Open+Sans:regular,semibold,italic,italicsemibold|Droid+Sans+Mono';
    +
    +  document.body.appendChild(el);
    +}
    +
    +function addGeneralStyle() {
    +  var el = document.createElement('link');
    +  el.rel = 'stylesheet';
    +  el.type = 'text/css';
    +  el.href = PERMANENT_URL_PREFIX + 'styles.css';
    +  document.body.appendChild(el);
    +
    +  var el = document.createElement('meta');
    +  el.name = 'viewport';
    +  el.content = 'width=device-width,height=device-height,initial-scale=1';
    +  document.querySelector('head').appendChild(el);
    +
    +  var el = document.createElement('meta');
    +  el.name = 'apple-mobile-web-app-capable';
    +  el.content = 'yes';
    +  document.querySelector('head').appendChild(el);
    +
    +  scaleSmallViewports();
    +}
    +
    +function handleDomLoaded() {
    +  slideEls = document.querySelectorAll('section.slides > article');
    +
    +  setupFrames();
    +
    +  addFontStyle();
    +  addGeneralStyle();
    +  addEventListeners();
    +
    +  updateSlides();
    +
    +  setupInteraction();
    +
    +  if (
    +    window.location.hostname == 'localhost' ||
    +    window.location.hostname == '127.0.0.1' ||
    +    window.location.hostname == '::1'
    +  ) {
    +    hideHelpText();
    +  }
    +
    +  document.body.classList.add('loaded');
    +
    +  setupNotesSync();
    +}
    +
    +function initialize() {
    +  getCurSlideFromHash();
    +
    +  if (window['_DEBUG']) {
    +    PERMANENT_URL_PREFIX = '../';
    +  }
    +
    +  if (window['_DCL']) {
    +    handleDomLoaded();
    +  } else {
    +    document.addEventListener('DOMContentLoaded', handleDomLoaded, false);
    +  }
    +}
    +
    +// If ?debug exists then load the script relative instead of absolute
    +if (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) {
    +  document.addEventListener(
    +    'DOMContentLoaded',
    +    function() {
    +      // Avoid missing the DomContentLoaded event
    +      window['_DCL'] = true;
    +    },
    +    false
    +  );
    +
    +  window['_DEBUG'] = true;
    +  var script = document.createElement('script');
    +  script.type = 'text/javascript';
    +  script.src = '../slides.js';
    +  var s = document.getElementsByTagName('script')[0];
    +  s.parentNode.insertBefore(script, s);
    +
    +  // Remove this script
    +  s.parentNode.removeChild(s);
    +} else {
    +  initialize();
    +}
    +
    +/* Synchronize windows when notes are enabled */
    +
    +function setupNotesSync() {
    +  if (!notesEnabled) return;
    +
    +  function setupPlayResizeSync() {
    +    var out = document.getElementsByClassName('output');
    +    for (var i = 0; i < out.length; i++) {
    +      $(out[i]).bind('resize', function(event) {
    +        if ($(event.target).hasClass('ui-resizable')) {
    +          localStorage.setItem('play-index', i);
    +          localStorage.setItem('output-style', out[i].style.cssText);
    +        }
    +      });
    +    }
    +  }
    +  function setupPlayCodeSync() {
    +    var play = document.querySelectorAll('div.playground');
    +    for (var i = 0; i < play.length; i++) {
    +      play[i].addEventListener('input', inputHandler, false);
    +
    +      function inputHandler(e) {
    +        localStorage.setItem('play-index', i);
    +        localStorage.setItem('play-code', e.target.innerHTML);
    +      }
    +    }
    +  }
    +
    +  setupPlayCodeSync();
    +  setupPlayResizeSync();
    +  localStorage.setItem(destSlideKey(), curSlide);
    +  window.addEventListener('storage', updateOtherWindow, false);
    +}
    +
    +// An update to local storage is caught only by the other window
    +// The triggering window does not handle any sync actions
    +function updateOtherWindow(e) {
    +  // Ignore remove storage events which are not meant to update the other window
    +  var isRemoveStorageEvent = !e.newValue;
    +  if (isRemoveStorageEvent) return;
    +
    +  var destSlide = localStorage.getItem(destSlideKey());
    +  while (destSlide > curSlide) {
    +    nextSlide();
    +  }
    +  while (destSlide < curSlide) {
    +    prevSlide();
    +  }
    +
    +  updatePlay(e);
    +  updateNotes();
    +}
    diff --git a/2025/06/16/google/request_id_files/styles.css b/2025/06/16/google/request_id_files/styles.css
    new file mode 100644
    index 0000000..47c9f19
    --- /dev/null
    +++ b/2025/06/16/google/request_id_files/styles.css
    @@ -0,0 +1,558 @@
    +@media screen {
    +  /* Framework */
    +  html {
    +    height: 100%;
    +  }
    +
    +  body {
    +    margin: 0;
    +    padding: 0;
    +
    +    display: block !important;
    +
    +    height: 100%;
    +    height: 100vh;
    +
    +    overflow: hidden;
    +
    +    background: rgb(215, 215, 215);
    +    background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
    +    background: -webkit-gradient(
    +      radial,
    +      50% 50%,
    +      0,
    +      50% 50%,
    +      500,
    +      from(rgb(240, 240, 240)),
    +      to(rgb(190, 190, 190))
    +    );
    +
    +    -webkit-font-smoothing: antialiased;
    +  }
    +
    +  .slides {
    +    width: 100%;
    +    height: 100%;
    +    left: 0;
    +    top: 0;
    +
    +    position: absolute;
    +
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +
    +  .slides > article {
    +    display: block;
    +
    +    position: absolute;
    +    overflow: hidden;
    +
    +    width: 900px;
    +    height: 700px;
    +
    +    left: 50%;
    +    top: 50%;
    +
    +    margin-left: -450px;
    +    margin-top: -350px;
    +
    +    padding: 40px 60px;
    +
    +    box-sizing: border-box;
    +    -o-box-sizing: border-box;
    +    -moz-box-sizing: border-box;
    +    -webkit-box-sizing: border-box;
    +
    +    border-radius: 10px;
    +    -o-border-radius: 10px;
    +    -moz-border-radius: 10px;
    +    -webkit-border-radius: 10px;
    +
    +    background-color: white;
    +
    +    border: 1px solid rgba(0, 0, 0, 0.3);
    +
    +    transition: transform 0.3s ease-out;
    +    -o-transition: -o-transform 0.3s ease-out;
    +    -moz-transition: -moz-transform 0.3s ease-out;
    +    -webkit-transition: -webkit-transform 0.3s ease-out;
    +  }
    +  .slides.layout-widescreen > article {
    +    margin-left: -550px;
    +    width: 1100px;
    +  }
    +  .slides.layout-faux-widescreen > article {
    +    margin-left: -550px;
    +    width: 1100px;
    +
    +    padding: 40px 160px;
    +  }
    +
    +  .slides.layout-widescreen > article:not(.nobackground):not(.biglogo),
    +  .slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) {
    +    background-position-x: 0, 840px;
    +  }
    +
    +  /* Clickable/tappable areas */
    +
    +  .slide-area {
    +    z-index: 1000;
    +
    +    position: absolute;
    +    left: 0;
    +    top: 0;
    +    width: 150px;
    +    height: 700px;
    +
    +    left: 50%;
    +    top: 50%;
    +
    +    cursor: pointer;
    +    margin-top: -350px;
    +
    +    tap-highlight-color: transparent;
    +    -o-tap-highlight-color: transparent;
    +    -moz-tap-highlight-color: transparent;
    +    -webkit-tap-highlight-color: transparent;
    +  }
    +  #prev-slide-area {
    +    margin-left: -550px;
    +  }
    +  #next-slide-area {
    +    margin-left: 400px;
    +  }
    +  .slides.layout-widescreen #prev-slide-area,
    +  .slides.layout-faux-widescreen #prev-slide-area {
    +    margin-left: -650px;
    +  }
    +  .slides.layout-widescreen #next-slide-area,
    +  .slides.layout-faux-widescreen #next-slide-area {
    +    margin-left: 500px;
    +  }
    +
    +  /* Slides */
    +
    +  .slides > article {
    +    display: none;
    +  }
    +  .slides > article.far-past {
    +    display: block;
    +    transform: translate(-2040px);
    +    -o-transform: translate(-2040px);
    +    -moz-transform: translate(-2040px);
    +    -webkit-transform: translate3d(-2040px, 0, 0);
    +  }
    +  .slides > article.past {
    +    display: block;
    +    transform: translate(-1020px);
    +    -o-transform: translate(-1020px);
    +    -moz-transform: translate(-1020px);
    +    -webkit-transform: translate3d(-1020px, 0, 0);
    +  }
    +  .slides > article.current {
    +    display: block;
    +    transform: translate(0);
    +    -o-transform: translate(0);
    +    -moz-transform: translate(0);
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +  .slides > article.next {
    +    display: block;
    +    transform: translate(1020px);
    +    -o-transform: translate(1020px);
    +    -moz-transform: translate(1020px);
    +    -webkit-transform: translate3d(1020px, 0, 0);
    +  }
    +  .slides > article.far-next {
    +    display: block;
    +    transform: translate(2040px);
    +    -o-transform: translate(2040px);
    +    -moz-transform: translate(2040px);
    +    -webkit-transform: translate3d(2040px, 0, 0);
    +  }
    +
    +  .slides.layout-widescreen > article.far-past,
    +  .slides.layout-faux-widescreen > article.far-past {
    +    display: block;
    +    transform: translate(-2260px);
    +    -o-transform: translate(-2260px);
    +    -moz-transform: translate(-2260px);
    +    -webkit-transform: translate3d(-2260px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.past,
    +  .slides.layout-faux-widescreen > article.past {
    +    display: block;
    +    transform: translate(-1130px);
    +    -o-transform: translate(-1130px);
    +    -moz-transform: translate(-1130px);
    +    -webkit-transform: translate3d(-1130px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.current,
    +  .slides.layout-faux-widescreen > article.current {
    +    display: block;
    +    transform: translate(0);
    +    -o-transform: translate(0);
    +    -moz-transform: translate(0);
    +    -webkit-transform: translate3d(0, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.next,
    +  .slides.layout-faux-widescreen > article.next {
    +    display: block;
    +    transform: translate(1130px);
    +    -o-transform: translate(1130px);
    +    -moz-transform: translate(1130px);
    +    -webkit-transform: translate3d(1130px, 0, 0);
    +  }
    +  .slides.layout-widescreen > article.far-next,
    +  .slides.layout-faux-widescreen > article.far-next {
    +    display: block;
    +    transform: translate(2260px);
    +    -o-transform: translate(2260px);
    +    -moz-transform: translate(2260px);
    +    -webkit-transform: translate3d(2260px, 0, 0);
    +  }
    +}
    +
    +@media print {
    +  /* Set page layout */
    +  @page {
    +    size: A4 landscape;
    +  }
    +
    +  body {
    +    display: block !important;
    +  }
    +
    +  .slides > article {
    +    display: block;
    +
    +    position: relative;
    +
    +    page-break-inside: never;
    +    page-break-after: always;
    +
    +    overflow: hidden;
    +  }
    +
    +  h2 {
    +    position: static !important;
    +    margin-top: 400px !important;
    +    margin-bottom: 100px !important;
    +  }
    +
    +  pre {
    +    background: rgb(240, 240, 240);
    +  }
    +
    +  /* Add explicit links */
    +  a:link:after,
    +  a:visited:after {
    +    content: ' (' attr(href) ') ';
    +    font-size: 50%;
    +  }
    +
    +  #help {
    +    display: none;
    +    visibility: hidden;
    +  }
    +}
    +
    +/* Styles for slides */
    +
    +.slides > article {
    +  font-family: 'Open Sans', Arial, sans-serif;
    +
    +  color: black;
    +  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
    +
    +  font-size: 26px;
    +  line-height: 36px;
    +
    +  letter-spacing: -1px;
    +}
    +
    +b {
    +  font-weight: 600;
    +}
    +
    +a {
    +  color: rgb(0, 102, 204);
    +  text-decoration: none;
    +}
    +a:visited {
    +  color: rgba(0, 102, 204, 0.75);
    +}
    +a:hover {
    +  color: black;
    +}
    +
    +p {
    +  margin: 0;
    +  padding: 0;
    +
    +  margin-top: 20px;
    +}
    +p:first-child {
    +  margin-top: 0;
    +}
    +
    +h1 {
    +  font-size: 60px;
    +  line-height: 60px;
    +
    +  padding: 0;
    +  margin: 0;
    +  margin-top: 200px;
    +  margin-bottom: 5px;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -3px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +h2 {
    +  font-size: 45px;
    +  line-height: 45px;
    +
    +  position: absolute;
    +  bottom: 150px;
    +
    +  padding: 0;
    +  margin: 0;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -2px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +h3 {
    +  font-size: 30px;
    +  line-height: 36px;
    +
    +  padding: 0;
    +  margin: 0;
    +  padding-right: 40px;
    +
    +  font-weight: 600;
    +
    +  letter-spacing: -1px;
    +
    +  color: rgb(51, 51, 51);
    +}
    +
    +ul {
    +  margin: 0;
    +  padding: 0;
    +  margin-top: 20px;
    +  margin-left: 1.5em;
    +}
    +li {
    +  padding: 0;
    +  margin: 0 0 0.5em 0;
    +}
    +
    +div.code, div.output {
    +  margin: 0;
    +  padding: 0;
    +}
    +
    +pre {
    +  padding: 5px 10px;
    +  margin-top: 20px;
    +  margin-bottom: 20px;
    +  overflow: hidden;
    +
    +  background: rgb(240, 240, 240);
    +  border: 1px solid rgb(224, 224, 224);
    +
    +  font-family: 'Droid Sans Mono', 'Courier New', monospace;
    +  font-size: 18px;
    +  line-height: 24px;
    +  letter-spacing: -1px;
    +
    +  color: black;
    +}
    +
    +pre.numbers span:before {
    +  content: attr(num);
    +  margin-right: 1em;
    +  display: inline-block;
    +}
    +
    +code {
    +  font-size: 95%;
    +  font-family: 'Droid Sans Mono', 'Courier New', monospace;
    +
    +  color: black;
    +}
    +
    +pre code {
    +  font-size: 100%;
    +}
    +
    +article > .image,
    +article > .video {
    +  text-align: center;
    +  margin-top: 40px;
    +}
    +
    +article.background {
    +  background-size: contain;
    +  background-repeat: round;
    +}
    +
    +table {
    +  width: 100%;
    +  border-collapse: collapse;
    +  margin-top: 40px;
    +}
    +th {
    +  font-weight: 600;
    +  text-align: left;
    +}
    +td,
    +th {
    +  border: 1px solid rgb(224, 224, 224);
    +  padding: 5px 10px;
    +  vertical-align: top;
    +}
    +
    +p.link {
    +  margin-left: 20px;
    +}
    +
    +.pagenumber {
    +  color: #8c8c8c;
    +  font-size: 75%;
    +  position: absolute;
    +  bottom: 0px;
    +  right: 10px;
    +}
    +
    +/* Code */
    +pre {
    +  outline: 0px solid transparent;
    +}
    +div.playground {
    +  position: relative;
    +}
    +div.output {
    +  position: absolute;
    +  left: 50%;
    +  top: 50%;
    +  right: 40px;
    +  bottom: 40px;
    +  background: #202020;
    +  padding: 5px 10px;
    +  z-index: 2;
    +
    +  border-radius: 10px;
    +  -o-border-radius: 10px;
    +  -moz-border-radius: 10px;
    +  -webkit-border-radius: 10px;
    +}
    +div.output pre {
    +  margin: 0;
    +  padding: 0;
    +  background: none;
    +  border: none;
    +  width: 100%;
    +  height: 100%;
    +  overflow: auto;
    +}
    +div.output .stdout,
    +div.output pre {
    +  color: #e6e6e6;
    +}
    +div.output .stderr,
    +div.output .error {
    +  color: rgb(255, 200, 200);
    +}
    +div.output .system,
    +div.output .exit {
    +  color: rgb(255, 230, 120);
    +}
    +.buttons {
    +  position: relative;
    +  float: right;
    +  top: -60px;
    +  right: 10px;
    +}
    +div.output .buttons {
    +  position: absolute;
    +  float: none;
    +  top: auto;
    +  right: 5px;
    +  bottom: 5px;
    +}
    +
    +/* Presenter details */
    +.presenter {
    +  margin-top: 20px;
    +}
    +.presenter p,
    +.presenter .link {
    +  margin: 0;
    +  font-size: 28px;
    +  line-height: 1.2em;
    +}
    +
    +/* Output resize details */
    +.ui-resizable-handle {
    +  position: absolute;
    +}
    +.ui-resizable-n {
    +  cursor: n-resize;
    +  height: 7px;
    +  width: 100%;
    +  top: -5px;
    +  left: 0;
    +}
    +.ui-resizable-w {
    +  cursor: w-resize;
    +  width: 7px;
    +  left: -5px;
    +  top: 0;
    +  height: 100%;
    +}
    +.ui-resizable-nw {
    +  cursor: nw-resize;
    +  width: 9px;
    +  height: 9px;
    +  left: -5px;
    +  top: -5px;
    +}
    +iframe {
    +  border: none;
    +}
    +figcaption {
    +  color: #666;
    +  text-align: center;
    +  font-size: 0.75em;
    +}
    +
    +#help {
    +  font-family: 'Open Sans', Arial, sans-serif;
    +  text-align: center;
    +  color: white;
    +  background: #000;
    +  opacity: 0.5;
    +  position: fixed;
    +  bottom: 25px;
    +  left: 50px;
    +  right: 50px;
    +  padding: 20px;
    +
    +  border-radius: 10px;
    +  -o-border-radius: 10px;
    +  -moz-border-radius: 10px;
    +  -webkit-border-radius: 10px;
    +}
    diff --git a/2025/06/16/google/request_id_files/xgoogrequestid-fields.webp b/2025/06/16/google/request_id_files/xgoogrequestid-fields.webp
    new file mode 100644
    index 0000000..3644a92
    Binary files /dev/null and b/2025/06/16/google/request_id_files/xgoogrequestid-fields.webp differ
    diff --git a/2025/06/16/google/xgoogrequestid-fields.webp b/2025/06/16/google/xgoogrequestid-fields.webp
    new file mode 100644
    index 0000000..3644a92
    Binary files /dev/null and b/2025/06/16/google/xgoogrequestid-fields.webp differ
    diff --git a/docs/README.md b/docs/README.md
    new file mode 100644
    index 0000000..9b69328
    --- /dev/null
    +++ b/docs/README.md
    @@ -0,0 +1 @@
    +# docs