summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Tay <sam.chong.tay@gmail.com>2020-06-24 16:48:36 -0700
committerSam Tay <sam.chong.tay@gmail.com>2020-06-25 02:10:33 -0700
commit3216d47824f3f15e11a60132b2c559fc4796d59c (patch)
treee237db0c84b27d6ba94769ff6e00a412c9d28118
parent1a18145d77b1605dab2d1b1cd18a8cf940ea489c (diff)
Update docs
-rw-r--r--Cargo.toml4
-rw-r--r--README.md139
-rw-r--r--TODO.md65
-rwxr-xr-xdocs/install.sh154
-rw-r--r--roadmap.md8
-rw-r--r--src/config.rs2
-rw-r--r--src/stackexchange/scraper.rs2
-rw-r--r--test/google/parsing-q.html197
8 files changed, 487 insertions, 84 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 24c1ebb..6755923 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,6 +11,10 @@ categories = ["command-line-utilities"]
authors = ["Sam Tay <sam.chong.tay@gmail.com>"]
edition = "2018"
+[badges]
+appveyor = { repository = "samtay/so", branch = "master", service = "github" }
+travis-ci = { repository = "samtay/so", branch = "master" }
+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
diff --git a/README.md b/README.md
index 7b773c3..90b6622 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,62 @@
+[![Build Status (travis)](https://travis-ci.org/samtay/so.svg?branch=master)](https://travis-ci.org/samtay/so)
+[![Build status](https://ci.appveyor.com/api/projects/status/pu7e63f2sqq6x1iq/branch/master?svg=true)](https://ci.appveyor.com/project/samtay/so/branch/master)
+
# so
+A terminal interface for StackOverflow.
+
+**Note**: still working out some kinks. Initial release not published just yet.
+**<Insert GIF here>**
+
+## example usage
+While I like the acronym *so*, this tool would actually be better described as
+*se*: an interface to the StackExchange network. In particular one thing that
+differentiates it from [similar](https://github.com/santinic/how2)
+[tools](https://github.com/gleitz/howdoi) is that you can simultaneously search
+any number of sites in the StackExchange network:
+```shell
+# use default configured sites, e.g. [stackoverflow.com]
+$ so how do i reverse a list in python
+
+# search for a latex solution
+$ so --site tex how to put tilde over character
+
+# use google to search stackoverflow.com, askubuntu.com, and unix.stackexchange.com
+$ so -e google -s askubuntu -s stackoverflow -s unix how do i install linux
+```
+
+## installation
+The quickest installation method is to download the appropriate
+binary from the [release artifacts](TODO link). Right now I'm only building the
+most common targets, but in theory it should be easy to add more, so if you
+don't see what you are looking for just open an issue and I can add it. Here's a
+list of the [supported
+targets](https://github.com/japaric/trust#supported-targets). You can quickly
+install the binary for your OS with:
+```shell
+$ curl -LSfs https://samtay.github.io/so/install.sh | \
+ sh -s -- --git samtay/so
+```
-**Note:** under development, not ready for prime time.
+#### cargo
+```
+cargo install so
+```
-# documentation
+## documentation
### api keys
-According to the [StackExchange
-docs](https://api.stackexchange.com/docs/throttle), most users should be fine
-without generating a personal API key (10k requests per IP per day). If you do
-run into throttling issues, get a key
-[here](https://stackapps.com/apps/oauth/register) and tell `so` to use it:
+If you want to use your own [StackExchange API
+Key](https://api.stackexchange.com/docs) you can set it via
```
so --set-api-key <KEY>
```
+You can also choose to use no key by editing your configuration to `api_key: ~`.
+If for some reason my API key is globally throttled, you can hit the
+StackExchange API with no key up to 300 times per day per IP, which I imagine is
+fine for most users.
### multi-site searching
-As stated in the docs linked above,
+As stated in the [docs](https://api.stackexchange.com/docs/throttle),
> If a single IP is making more than 30 requests a second, new requests will be dropped.
@@ -23,49 +64,45 @@ So, don't go crazy with the multi-site search, since it is all done in parallel.
In particular, if you specify more than 30 sites, SE will likely ban you for a short time.
### selecting a backend
-Crossterm's level of support is awesome, but it comes at a price. On my machine,
-the app kind of flashes between draws quite a bit. If you are on Mac, Linux, or
-Redox, your best bet is to compile with default features which uses the
-termion backend. If you are on windows, use crossterm, but know it will be
-slightly jumpy.
-
-If the crossterm folks figure out a fix for [allowing ncurses to receive resize events](),
-and you have ncurses installed on your system, then you should use the
-ncurses backend, or the pancurses backend if you are on Windows. Just know that
-currently if you choose this option, you won't be able to resize the terminal
-window while the TUI is open.
-
-default = ["cursive/termion-backend"]
-ncurses-backend = ["cursive/ncurses-backend"]
-pancurses-backend = ["cursive/pancurses-backend"]
-crossterm-backend = ["cursive/crossterm-backend"]
-
-# notes to self
-
-### async considerations
-Implemented async with tokio in ec92f93, but unclear if this is necessary. For
-< 10 simultaneous network requests, it might be better and simpler to just use
-rayon (i.e. OS threads).
-
-### TUI considerations
-Going with cursive because it is way more flexible than tui-rs.
-**Important note** Tables are not currently allowed in stackexchange... so the
-benefit of incorporating termimad features will not be felt. But, this is
-changing [soon](https://meta.stackexchange.com/q/348746).
-
-### to stress test
-Produces a long answer with noticeable pause on markdown view:
+If you're installing from source, you can choose from a number of available
+backend rendering engines. Note that the package `default` and `windows` feature
+flags do not have an ncurses dependency, for the sake of simplicity. The
+default backend is [termion](https://github.com/redox-os/termion), a bindless
+library in pure Rust which seems to work quite well on Linux, MacOS, BSD, and
+Redox. The windows backend is by default
+[crossterm](https://github.com/crossterm-rs/crossterm), and while its level of
+support is awesome, it does comes at a price in performance. On my machine, the
+app kind of flashes between draws quite a bit. So if you are on Mac, Linux, or
+Redox, your best bet is to compile with default features which uses the termion
+backend. If you are on windows, use crossterm, but know it will be slightly
+jumpy.
+
+If the crossterm folks figure out a fix for allowing ncurses to receive [resize
+events](https://github.com/crossterm-rs/crossterm/issues/447), and you have
+[ncurses installed](https://github.com/gyscos/cursive/wiki/Install-ncurses) on
+your system, then the ncurses and pancurses backends will also work well.
+Just know that *currently* if you choose this option, and you run the `--lucky`
+prompt, you won't be able to resize the terminal window while the TUI is open.
+
+Available backends:
+- `termion-backend`
+- `ncurses-backend`
+- `pancurses-backend`
+- `crossterm-backend`
+
+E.g. to use `ncurses-backend`:
```
-cargo run -- --site stackoverflow --site serverfault how do I exit Vim
+cargo install so --no-default-features --features ncurses-backend
```
-### to troubleshoot
-```
-export RUST_BACKTRACE=full
-cargo run -- how do I exit Vim > test.txt 2>&1
-```
-
-
-
-
-**Remove this** Recall my api key is: `8o9g7WcfwnwbB*Qp4VsGsw((`
+See more information on this choice
+[here](https://github.com/gyscos/cursive/wiki/Backends).
+
+## contributions
+This was my first time writing Rust, and I wrote about it
+[here](https://samtay.github.io/TODO) if you're into that sort of thing.
+I just want to put out a **warning** that there is very likely some non-idiomatic
+and straight up ugly code throughout this project, so don't come looking here
+for a good Rust example! That being said, I would love to improve the codebase
+so if you have any refactoring contributions feel free to send me a PR, but
+please also accompany them with a short explanation.
diff --git a/TODO.md b/TODO.md
index 04cd41f..ce81bd3 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,11 +1,29 @@
# TODO
-1. Use trust to make cross platform binaries
-2. Make an example GIF
-3. Shore up the README
-4. Add license file
+### chores
+1. Make an example GIF
+2. Move to github actions ASAP, travis & appveyor are a PITA. See resources below.
+3. Benchmark parsing. Probaly way faster to use regex to find question IDs
+ within URLs (or the entire doc).
-### Endless future improvements for the TUI
+### bugs
+1. Need to also allow /q/ in search results in addition to /questions/
+2.
+```
+so --search-engine google --site stackoverflow --site askubuntu how to stop typing sudo
+```
+results in
+```
+thread '<unnamed>' panicked at 'assertion failed: value_pos >= source_pos', /home/sam/.cargo/registry/src/github.com-1ecc6299db9ec823/cursive_core-0.1.0/src/utils/span.rs:372:17
+```
+So maybe the md parser should just build its own source for
+SpannedString, and own everything...
+
+### feature ideas
+- Add sort option, e.g. relevance|votes|date
+- Keep track of quota in a data file, inform user when getting close?
+
+#### Endless improvements for the TUI
3. Small text at bottom with '?' to bring up key mapping dialog
1. Init with smaller layout depending on initial screen size.
2. Maybe cli `--auto-resize` option that changes layouts at breakpoints.
@@ -15,27 +33,20 @@
or just hardcoded ones.
7. Small tray at the bottom with "notifications", e.g. "GitHub Theme loaded!"
-### resources for later
+**Important note:** Tables are not currently allowed in stackexchange... so the
+benefit of incorporating termimad features into a cursive view will not be felt.
+But, this is changing [soon](https://meta.stackexchange.com/q/348746).
-#### scraping
-```python
-# if necessary, cycle through these to mimic browser request
-USER_AGENTS = ('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:11.0) Gecko/20100101 Firefox/11.0',
-'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100 101 Firefox/22.0',
-'Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0',
-('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) '
-'Chrome/19.0.1084.46 Safari/536.5'),
-('Mozilla/5.0 (Windows; Windows NT 6.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46'
-'Safari/536.5'), )
-
-# checks for search engine blocks
-BLOCK_INDICATORS = (
- 'form id="captcha-form"',
- 'This page appears when Google automatically detects requests coming from your computer '
- 'network which appear to be in violation of the <a href="//www.google.com/policies/terms/">Terms of Service'
-)
-```
-#### ideas
-5. Add sort option, e.g. relevance|votes|date
-8. Keep track of quota in a data file, inform user when getting close?
+### resources for later
+- [Trust example](https://github.com/badboy/signify-rs)
+- [Github Actions example](https://github.com/extrawurst/gitui)
+- [logging example](https://deterministic.space/rust-cli-tips.html)
+- [PKGBUILD example](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=gitui) + openssl dep
+- More mock user agents
+ - Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:11.0) Gecko/20100101 Firefox/11.0
+ - Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100 101 Firefox/22.0
+ - Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0
+ - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5
+ - Mozilla/5.0 (Windows; Windows NT 6.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5
+
diff --git a/docs/install.sh b/docs/install.sh
new file mode 100755
index 0000000..a3f55ea
--- /dev/null
+++ b/docs/install.sh
@@ -0,0 +1,154 @@
+#!/bin/sh
+
+set -e
+
+help() {
+ cat <<'EOF'
+Install a binary release of a Rust crate hosted on GitHub
+
+Usage:
+ install.sh [options]
+
+Options:
+ -h, --help Display this message
+ --git SLUG Get the crate from "https://github/$SLUG"
+ -f, --force Force overwriting an existing binary
+ --crate NAME Name of the crate to install (default <repository name>)
+ --tag TAG Tag (version) of the crate to install (default <latest release>)
+ --target TARGET Install the release compiled for $TARGET (default <`rustc` host>)
+ --to LOCATION Where to install the binary (default ~/.cargo/bin)
+EOF
+}
+
+say() {
+ echo "install.sh: $1"
+}
+
+say_err() {
+ say "$1" >&2
+}
+
+err() {
+ if [ ! -z $td ]; then
+ rm -rf $td
+ fi
+
+ say_err "ERROR $1"
+ exit 1
+}
+
+need() {
+ if ! command -v $1 > /dev/null 2>&1; then
+ err "need $1 (command not found)"
+ fi
+}
+
+force=false
+while test $# -gt 0; do
+ case $1 in
+ --crate)
+ crate=$2
+ shift
+ ;;
+ --force | -f)
+ force=true
+ ;;
+ --git)
+ git=$2
+ shift
+ ;;
+ --help | -h)
+ help
+ exit 0
+ ;;
+ --tag)
+ tag=$2
+ shift
+ ;;
+ --target)
+ target=$2
+ shift
+ ;;
+ --to)
+ dest=$2
+ shift
+ ;;
+ *)
+ ;;
+ esac
+ shift
+done
+
+# Dependencies
+need basename
+need curl
+need install
+need mkdir
+need mktemp
+need tar
+
+# Optional dependencies
+if [ -z $crate ] || [ -z $tag ] || [ -z $target ]; then
+ need cut
+fi
+
+if [ -z $tag ]; then
+ need rev
+fi
+
+if [ -z $target ]; then
+ need grep
+ need rustc
+fi
+
+if [ -z $git ]; then
+ err 'must specify a git repository using `--git`. Example: `install.sh --git japaric/cross`'
+fi
+
+url="https://github.com/$git"
+say_err "GitHub repository: $url"
+
+if [ -z $crate ]; then
+ crate=$(echo $git | cut -d'/' -f2)
+fi
+
+say_err "Crate: $crate"
+
+url="$url/releases"
+
+if [ -z $tag ]; then
+ tag=$(curl -s "$url/latest" | cut -d'"' -f2 | rev | cut -d'/' -f1 | rev)
+ say_err "Tag: latest ($tag)"
+else
+ say_err "Tag: $tag"
+fi
+
+if [ -z $target ]; then
+ target=$(rustc -Vv | grep host | cut -d' ' -f2)
+fi
+
+say_err "Target: $target"
+
+if [ -z $dest ]; then
+ dest="$HOME/.cargo/bin"
+fi
+
+say_err "Installing to: $dest"
+
+url="$url/download/$tag/$crate-$tag-$target.tar.gz"
+
+td=$(mktemp -d || mktemp -d -t tmp)
+curl -sL $url | tar -C $td -xz
+
+for f in $(ls $td); do
+ test -x $td/$f || continue
+
+ if [ -e "$dest/$f" ] && [ $force = false ]; then
+ err "$f already exists in $dest"
+ else
+ mkdir -p $dest
+ install -m 755 $td/$f $dest
+ fi
+done
+
+rm -rf $td
diff --git a/roadmap.md b/roadmap.md
index f79b693..3a9c73a 100644
--- a/roadmap.md
+++ b/roadmap.md
@@ -27,13 +27,11 @@
[x] Add google scraper
### at some point
-[ ] look up how to add `debug!` macros; will help troubleshooting blocked requests
-[ ] use trust to distrubute app binaries
-[ ] ask SE forums if I should bundle my api-key? (if so use an env var macro)
+[ ] look up how to add logging `debug!` macros; will help troubleshooting blocked requests
+[x] use trust to distrubute app binaries
[ ] allow new queries from TUI, e.g. hit `/` for a prompt
[ ] or `/` searches current q/a
-[ ] clean up dingleberries in error.rs and term.rs ; only keep whats actually ergonomic
-[ ] ask legal@stackoverflow.com for permission to logo stackoverflow/stackexchange in readme
+[ ] clean up dingleberries in error.rs and term.rs ; only keep what's actually ergonomic
[ ] add duckduckgo logo to readme
[ ] per platform package mgmt
[ ] more testing
diff --git a/src/config.rs b/src/config.rs
index 0154cda..987a887 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -47,7 +47,7 @@ impl Default for SearchEngine {
impl Default for Config {
fn default() -> Self {
Config {
- api_key: None,
+ api_key: Some(String::from("8o9g7WcfwnwbB*Qp4VsGsw((")),
limit: 20,
lucky: true,
sites: vec![String::from("stackoverflow")],
diff --git a/src/stackexchange/scraper.rs b/src/stackexchange/scraper.rs
index 2f62eb6..b03c577 100644
--- a/src/stackexchange/scraper.rs
+++ b/src/stackexchange/scraper.rs
@@ -176,6 +176,7 @@ fn parse_with_selector(
})
}
+// TODO also allow /q/
/// For example
/// ```
/// let id = "stackoverflow.com";
@@ -191,6 +192,7 @@ fn question_url_to_id(site_url: &str, input: &str) -> Option<String> {
Some(input[0..end].to_string())
}
+// TODO test with google/parsing-q.html
#[cfg(test)]
mod tests {
use super::*;
diff --git a/test/google/parsing-q.html b/test/google/parsing-q.html
new file mode 100644
index 0000000..bcb7b19
--- /dev/null
+++ b/test/google/parsing-q.html
@@ -0,0 +1,197 @@
+<!doctype html><html itemscope="" itemtype="http://schema.org/SearchResultsPage" lang="en"><head><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>(site:stackoverflow.com) how do i reverse a list in python - Google Search</title><script nonce="c+l/vHKNHR/yfOloi+dylw==">(function(){window.google={kEI:'hN_zXrjDAqSUmAXxzb5o',kEXPI:'31',kBL:'tdrq'};google.sn='web';google.kHL='en';})();(function(){google.lc=[];google.li=0;google.getEI=function(a){for(var c;a&&(!a.getAttribute||!(c=a.getAttribute("eid")));)a=a.parentNode;return c||google.kEI};google.getLEI=function(a){for(var c=null;a&&(!a.getAttribute||!(c=a.getAttribute("leid")));)a=a.parentNode;return c};google.ml=function(){return null};google.time=function(){return Date.now()};google.log=function(a,c,b,d,g){if(b=google.logUrl(a,c,b,d,g)){a=new Image;var e=google.lc,f=google.li;e[f]=a;a.onerror=a.onload=a.onabort=function(){delete e[f]};google.vel&&google.vel.lu&&google.vel.lu(b);a.src=b;google.li=f+1}};google.logUrl=function(a,c,b,d,g){var e="",f=google.ls||"";b||-1!=c.search("&ei=")||(e="&ei="+google.getEI(d),-1==c.search("&lei=")&&(d=google.getLEI(d))&&(e+="&lei="+d));d="";!b&&google.cshid&&-1==c.search("&cshid=")&&"slh"!=a&&(d="&cshid="+google.cshid);b=b||"/"+(g||"gen_204")+"?atyp=i&ct="+a+"&cad="+c+e+f+"&zx="+google.time()+d;/^http:/i.test(b)&&"https:"==window.location.protocol&&(google.ml(Error("a"),!1,{src:b,glmm:1}),b="");return b};}).call(this);(function(){google.y={};google.x=function(a,b){if(a)var c=a.id;else{do c=Math.random();while(google.y[c])}google.y[c]=[a,b];return!1};google.lm=[];google.plm=function(a){google.lm.push.apply(google.lm,a)};google.lq=[];google.load=function(a,b,c){google.lq.push([[a],b,c])};google.loadAll=function(a,b){google.lq.push([a,b])};}).call(this);google.f={};(function(){
+document.documentElement.addEventListener("submit",function(b){var a;if(a=b.target){var c=a.getAttribute("data-submitfalse");a="1"==c||"q"==c&&!a.elements.q.value?!0:!1}else a=!1;a&&(b.preventDefault(),b.stopPropagation())},!0);document.documentElement.addEventListener("click",function(b){var a;a:{for(a=b.target;a&&a!=document.documentElement;a=a.parentElement)if("A"==a.tagName){a="1"==a.getAttribute("data-nohref");break a}a=!1}a&&b.preventDefault()},!0);}).call(this);(function(){google.hs={h:true,sie:false};})();var h="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a},k=function(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("a");},l=k(this),m=function(a,b){if(b)a:{var c=l;a=a.split(".");for(var d=0;d<a.length-1;d++){var e=a[d];if(!(e in
+c))break a;c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&h(c,a,{configurable:!0,writable:!0,value:b})}};m("String.prototype.startsWith",function(a){return a?a:function(b,c){if(null==this)throw new TypeError("The 'this' value for String.prototype.startsWith must not be null or undefined");if(b instanceof RegExp)throw new TypeError("First argument to String.prototype.startsWith must not be a regular expression");var d=this+"";b+="";var e=d.length,g=b.length;c=Math.max(0,Math.min(c|0,d.length));for(var f=0;f<g&&c<e;)if(d[c++]!=b[f++])return!1;return f>=g}});google.arwt=function(a){a.href=document.getElementById(a.id.substring(a.id.startsWith("vcs")?3:1)).href;return!0};(function(){
+var f=this||self,h=Date.now;
+
+var x={};var aa=function(a,c){if(null===c)return!1;if("contains"in a&&1==c.nodeType)return a.contains(c);if("compareDocumentPosition"in a)return a==c||!!(a.compareDocumentPosition(c)&16);for(;c&&a!=c;)c=c.parentNode;return c==a};var ba=function(a,c){return function(d){d||(d=window.event);return c.call(a,d)}},z=function(a){a=a.target||a.srcElement;!a.getAttribute&&a.parentNode&&(a=a.parentNode);return a},A="undefined"!=typeof navigator&&/Macintosh/.test(navigator.userAgent),ca="undefined"!=typeof navigator&&!/Opera/.test(navigator.userAgent)&&/WebKit/.test(navigator.userAgent),da={A:1,INPUT:1,TEXTAREA:1,SELECT:1,BUTTON:1},ea=function(){this._mouseEventsPrevented=!0},F={A:13,BUTTON:0,CHECKBOX:32,COMBOBOX:13,FILE:0,GRIDCELL:13,LINK:13,LISTBOX:13,MENU:0,MENUBAR:0,MENUITEM:0,MENUITEMCHECKBOX:0,MENUITEMRADIO:0,OPTION:0,RADIO:32,RADIOGROUP:32,RESET:0,SUBMIT:0,SWITCH:32,TAB:0,TREE:13,TREEITEM:13},G={CHECKBOX:!0,FILE:!0,OPTION:!0,RADIO:!0},H={COLOR:!0,DATE:!0,DATETIME:!0,"DATETIME-LOCAL":!0,EMAIL:!0,MONTH:!0,NUMBER:!0,PASSWORD:!0,RANGE:!0,SEARCH:!0,TEL:!0,TEXT:!0,TEXTAREA:!0,TIME:!0,URL:!0,WEEK:!0},fa={A:!0,AREA:!0,BUTTON:!0,DIALOG:!0,IMG:!0,INPUT:!0,LINK:!0,MENU:!0,OPTGROUP:!0,OPTION:!0,PROGRESS:!0,SELECT:!0,TEXTAREA:!0};
+var I=function(){this.h=this.a=null},K=function(a,c){var d=J;d.a=a;d.h=c;return d};I.prototype.g=function(){var a=this.a;this.a&&this.a!=this.h?this.a=this.a.__owner||this.a.parentNode:this.a=null;return a};var L=function(){this.i=[];this.a=0;this.h=null;this.j=!1};L.prototype.g=function(){if(this.j)return J.g();if(this.a!=this.i.length){var a=this.i[this.a];this.a++;a!=this.h&&a&&a.__owner&&(this.j=!0,K(a.__owner,this.h));return a}return null};var J=new I,M=new L;
+var O=function(){this.o=[];this.a=[];this.g=[];this.j={};this.h=null;this.i=[];N(this,"_custom")},ha="undefined"!=typeof navigator&&/iPhone|iPad|iPod/.test(navigator.userAgent),P=String.prototype.trim?function(a){return a.trim()}:function(a){return a.replace(/^\s+/,"").replace(/\s+$/,"")},ia=/\s*;\s*/,ma=function(a,c){return function p(b,g){g=void 0===g?!0:g;var m=c;if("_custom"==m){m=b.detail;if(!m||!m._type)return;m=m._type}if("click"==m&&(A&&b.metaKey||!A&&b.ctrlKey||2==b.which||null==b.which&&
+4==b.button||b.shiftKey))m="clickmod";else{var l=b.which||b.keyCode;ca&&3==l&&(l=13);if(13!=l&&32!=l)l=!1;else{var e=z(b),n;(n="keydown"!=b.type||!!(!("getAttribute"in e)||(e.getAttribute("type")||e.tagName).toUpperCase()in H||"BUTTON"==e.tagName.toUpperCase()||e.type&&"FILE"==e.type.toUpperCase()||e.isContentEditable)||b.ctrlKey||b.shiftKey||b.altKey||b.metaKey||(e.getAttribute("type")||e.tagName).toUpperCase()in G&&32==l)||((n=e.tagName in da)||(n=e.getAttributeNode("tabindex"),n=null!=n&&n.specified),n=!(n&&!e.disabled));if(n)l=!1;else{n=(e.getAttribute("role")||e.type||e.tagName).toUpperCase();var q=!(n in F)&&13==l;e="INPUT"!=e.tagName.toUpperCase()||!!e.type;l=(0==F[n]%l||q)&&e}}l&&(m="clickkey")}e=b.srcElement||b.target;l=Q(m,b,e,"",null);b.path?(M.i=b.path,M.a=0,M.h=this,M.j=!1,n=M):n=K(e,this);for(;q=n.g();){var k=q;var r=void 0;var u=k;q=m;var t=u.__jsaction;if(!t){var y;t=null;"getAttribute"in u&&(t=u.getAttribute("jsaction"));if(y=t){t=x[y];if(!t){t={};for(var B=y.split(ia),ja=B?B.length:0,C=0;C<ja;C++){var w=B[C];if(w){var D=w.indexOf(":"),R=-1!=D,ka=R?P(w.substr(0,D)):"click";w=R?P(w.substr(D+1)):w;t[ka]=w}}x[y]=t}u.__jsaction=t}else t=la,u.__jsaction=t}u=t;"maybe_click"==q&&u.click?(r=q,q="click"):"clickkey"==q?q="click":"click"!=q||u.click||(q="clickonly");r={m:r?r:q,action:u[q]||"",event:null,s:!1};l=Q(r.m,r.event||b,e,r.action||"",k,l.timeStamp);if(r.s||r.action)break}l&&"touchend"==l.eventType&&(l.event._preventMouseEvents=ea);if(r&&r.action){if(e="clickkey"==m)e=z(b),e=(e.type||
+e.tagName).toUpperCase(),(e=32==(b.which||b.keyCode)&&"CHECKBOX"!=e)||(e=z(b),n=e.tagName.toUpperCase(),r=(e.getAttribute("role")||"").toUpperCase(),e="BUTTON"===n||"BUTTON"===r?!0:!(e.tagName.toUpperCase()in fa)||"A"===n||"SELECT"===n||(e.getAttribute("type")||e.tagName).toUpperCase()in G||(e.getAttribute("type")||e.tagName).toUpperCase()in H?!1:!0);e&&(b.preventDefault?b.preventDefault():b.returnValue=!1);if("mouseenter"==m||"mouseleave"==m)if(e=b.relatedTarget,!("mouseover"==b.type&&"mouseenter"==
+m||"mouseout"==b.type&&"mouseleave"==m)||e&&(e===k||aa(k,e)))l.action="",l.actionElement=null;else{m={};for(var v in b)"function"!==typeof b[v]&&"srcElement"!==v&&"target"!==v&&(m[v]=b[v]);m.type="mouseover"==b.type?"mouseenter":"mouseleave";m.target=m.srcElement=k;m.bubbles=!1;l.event=m;l.targetElement=k}}else l.action="",l.actionElement=null;k=l;a.h&&!k.event.a11ysgd&&(v=Q(k.eventType,k.event,k.targetElement,k.action,k.actionElement,k.timeStamp),"clickonly"==v.eventType&&(v.eventType="click"),a.h(v,!0));if(k.actionElement){if(a.h){if(!k.actionElement||"A"!=k.actionElement.tagName||"click"!=k.eventType&&"clickmod"!=k.eventType||(b.preventDefault?b.preventDefault():b.returnValue=!1),(b=a.h(k))&&g){p.call(this,b,!1);return}}else{if((g=f.document)&&!g.createEvent&&g.createEventObject)try{var E=g.createEventObject(b)}catch(pa){E=b}else E=b;k.event=E;a.i.push(k)}if("touchend"==k.event.type&&k.event._mouseEventsPrevented){b=k.event;for(var qa in b);h()}}}},Q=function(a,c,d,b,g,p){return{eventType:a,event:c,targetElement:d,action:b,actionElement:g,timeStamp:p||h()}},la={},na=function(a,c){return function(d){var b=a,g=c,p=!1;"mouseenter"==b?b="mouseover":"mouseleave"==b&&(b="mouseout");if(d.addEventListener){if("focus"==b||"blur"==b||"error"==b||"load"==b)p=!0;d.addEventListener(b,g,p)}else d.attachEvent&&("focus"==b?b="focusin":"blur"==b&&(b="focusout"),g=ba(d,g),d.attachEvent("on"+b,g));return{m:b,l:g,capture:p}}},N=function(a,c){if(!a.j.hasOwnProperty(c)){var d=ma(a,c),b=na(c,d);a.j[c]=d;a.o.push(b);for(d=0;d<a.a.length;++d){var g=a.a[d];g.g.push(b.call(null,g.a))}"click"==c&&N(a,"keydown")}};O.prototype.l=function(a){return this.j[a]};var V=function(a,c){var d=new oa(c);a:{for(var b=0;b<a.a.length;b++)if(S(a.a[b],c)){c=!0;break a}c=!1}if(c)return a.g.push(d),d;T(a,d);a.a.push(d);U(a);return d},U=function(a){for(var c=a.g.concat(a.a),d=[],b=[],g=0;g<a.a.length;++g){var p=a.a[g];W(p,c)?(d.push(p),X(p)):b.push(p)}for(g=0;g<a.g.length;++g)p=a.g[g],W(p,c)?d.push(p):(b.push(p),T(a,p));a.a=b;a.g=d},T=function(a,c){var d=c.a;ha&&(d.style.cursor="pointer");for(d=0;d<a.o.length;++d)c.g.push(a.o[d].call(null,c.a))},Y=function(a,c){a.h=c;a.i&&(0<a.i.length&&c(a.i),a.i=null)},oa=function(a){this.a=a;this.g=[]},S=function(a,c){for(a=a.a;a!=c&&c.parentNode;)c=c.parentNode;return a==c},W=function(a,c){for(var d=0;d<c.length;++d)if(c[d].a!=a.a&&S(c[d],a.a))return!0;return!1},X=function(a){for(var c=0;c<a.g.length;++c){var d=a.a,b=a.g[c];d.removeEventListener?d.removeEventListener(b.m,b.l,b.capture):d.detachEvent&&d.detachEvent("on"+b.m,b.l)}a.g=[]};var Z=new O;V(Z,window.document.documentElement);N(Z,"click");N(Z,"focus");N(Z,"focusin");N(Z,"blur");N(Z,"focusout");N(Z,"error");N(Z,"load");N(Z,"change");N(Z,"dblclick");N(Z,"input");N(Z,"keyup");N(Z,"keydown");N(Z,"keypress");N(Z,"mousedown");N(Z,"mouseenter");N(Z,"mouseleave");N(Z,"mouseout");N(Z,"mouseover");N(Z,"mouseup");N(Z,"paste");N(Z,"touchstart");N(Z,"touchend");N(Z,"touchcancel");N(Z,"speech");(function(a){google.jsad=function(c){Y(a,c)};google.jsaac=function(c){return V(a,c)};google.jsarc=function(c){X(c);for(var d=!1,b=0;b<a.a.length;++b)if(a.a[b]===c){a.a.splice(b,1);d=!0;break}if(!d)for(d=0;d<a.g.length;++d)if(a.g[d]===c){a.g.splice(d,1);break}U(a)}})(Z);window.gws_wizbind=function(a){return{trigger:function(c){var d=a.l(c.type);d||(N(a,c.type),d=a.l(c.type));var b=c.target||c.srcElement;d&&d.call(b.ownerDocument.documentElement,c)},bind:function(c){Y(a,c)}}}(Z);}).call(this);(function(){
+var b=[];google.jsc={xx:b,x:function(a){b.push(a)},mm:[],m:function(a){google.jsc.mm.length||(google.jsc.mm=a)}};}).call(this);(function(){google.c={gl:false,inp:false,lhc:false,slp:false,uio:false,ust:false};(function(){
+var e=window.performance;var g=function(a,b,c,d){a.addEventListener?a.removeEventListener(b,c,d||!1):a.attachEvent&&a.detachEvent("on"+b,c)},h=function(a,b,c,d){a.addEventListener?a.addEventListener(b,c,d||!1):a.attachEvent&&a.attachEvent("on"+b,c)};google.timers={};google.startTick=function(a){google.timers[a]={t:{start:google.time()},e:{},m:{}}};google.tick=function(a,b,c){google.timers[a]||google.startTick(a);c=void 0!==c?c:google.time();b instanceof Array||(b=[b]);for(var d=0,f;f=b[d++];)google.timers[a].t[f]=c};google.c.e=function(a,b,c){google.timers[a].e[b]=c};google.c.b=function(a){var b=google.timers.load.m;b[a]&&google.ml(Error("a"),!1,{m:a});b[a]=!0};google.c.u=function(a){var b=google.timers.load.m;if(b[a]){b[a]=!1;for(a in b)if(b[a])return;google.csiReport()}else google.ml(Error("b"),!1,{m:a})};google.rll=function(a,b,c){var d=function(f){c(f);g(a,"load",d);g(a,"error",d)};h(a,"load",d);b&&h(a,"error",d)};google.aft=function(a){a.setAttribute("data-iml",google.time())};google.startTick("load");var k=google.timers.load;a:{var l=k.t;if(e){var m=e.timing;if(m){var n=m.navigationStart,p=m.responseStart;if(p>n&&p<=l.start){l.start=p;k.wsrt=p-n;break a}}e.now&&(k.wsrt=Math.floor(e.now()))}}google.c.b("pr");google.c.b("xe");if(google.c.gl){var q=function(a){a&&google.aft(a.target)};h(document.documentElement,"load",q,!0);google.c.glu=function(){g(document.documentElement,"load",q,!0)}};}).call(this);})();</script><style>[dir='ltr'],[dir='rtl']{unicode-bidi:-moz-isolate;unicode-bidi:isolate}bdo[dir='ltr'],bdo[dir='rtl']{unicode-bidi:bidi-override;unicode-bidi:-moz-isolate-override;unicode-bidi:isolate-override}#logocont{z-index:1;padding-left:16px;padding-right:10px;margin-top:-2px;padding-top:7px}#logocont.ddl{padding-top:3px}.big #logocont{padding-left:16px;padding-right:12px}#searchform #logocont{padding-top:11px;padding-right:28px;padding-left:30px}.sbibod{background-color:#fff;height:44px;vertical-align:top;border:1px solid #dfe1e5;border-radius:8px;box-shadow:none;transition:box-shadow 200ms cubic-bezier(0.4, 0.0, 0.2, 1);}.lst{border:0;margin-top:5px;margin-bottom:0}.lst:focus{outline:none}#lst-ib{color:#000}.gsfi,.lst{font:16px arial,sans-serif;line-height:34px;height:34px !important}.lst-c{overflow:hidden}#gs_st0{line-height:44px;padding:0 8px;margin-top:-1px;position:static}.srp #gs_st0{padding:0 2px 0 8px}.gsfs{font:17px arial,sans-serif}.lsb{background:transparent;border:0;font-size:0;height:30px;outline:0;text-align:left;width:100%}.sbico{display:inline-block;height:0px;width:0px;cursor:pointer;vertical-align:middle;color:#4285f4}.sbico-c{background:transparent;border:0;float:right;height:44px;line-height:44px;margin-top:-1px;outline:0;padding-right:16px;position:relative;top:-1px}.hp .sbico-c{display:none}#sblsbb{border-bottom-left-radius:0;border-top-left-radius:0;height:44px;margin:0;padding:0;}#sbds{border:0;margin-left:-1px}.hp .nojsb,.srp .jsb{display:none}#sfopt{display:inline-block;line-height:normal}.lsd{font-size:11px;position:absolute;top:3px;left:16px}.tsf{background:none}#sform{height:65px}#searchform{width:100%}.minidiv #gb{top:2px}.minidiv .sfbg{background:#fff;box-shadow:0 1px 6px 0 rgba(32,33,36,.28);height:72px;}.minidiv .sbibod{height:32px;margin:10px 0;border-radius:16px}.minidiv .visible-suggestions{border-bottom-left-radius:0;border-bottom-right-radius:0}.minidiv .sbico-c{height:32px;line-height:32px}.minidiv .sbib_b{padding-top:0}.minidiv .gsfi{font-size:14px;line-height:32px}.minidiv .gsfs{font-size:14px}.minidiv #logo img{height:28px;width:86px}#searchform.minidiv #logocont{padding:17px 34px 0}.minidiv li.sbsb_c .sbse{padding:0px 0}.minidiv .sbdd_a .sbdd_b,.minidiv .sbsb_a{border-bottom-left-radius:16px;border-bottom-right-radius:16px}.minidiv #gs_st0{line-height:32px !important}.minidiv .sbdd_a{top:32px !important}.minidiv .gsri_a{background-size:20px 20px;height:20px;width:16px}.minidiv .sbico-c .sbico{height:20px;width:20px}.hp #searchform{position:absolute;top:311px}@media only screen and (max-height:768px){.hp #searchform{top:269px}}.srp #searchform{position:absolute;top:20px;}.sfbg{height:69px;left:0;position:absolute;width:100%}.sfbgg{height:65px}#cnt{padding-top:20px;}</style><style id="gstyle">body{background:#fff;color:#000;margin:0}.link{color:#1a0dab !important}.ts{border-collapse:collapse}.ts td{padding:0}.g{line-height:1.2;text-align:left;width:600px}#rhs{padding-bottom:15px}a:link,.q:active,.q:visited{color:#1a0dab}a:visited{color:#609}.b{font-weight:bold}.s{max-width:48em}.sl{font-size:82%}.f,.f a:link{color:#70757a;line-height:1.58}.c h2{color:#666}.mslg cite{display:none}h1,ol,ul,li{margin:0;padding:0}.g,body,html,input,.std,h1{font-family:arial,sans-serif}.g,body,input,.std,h1{font-size:14px}.c h2,h1{font-weight:normal}h3,.med{font-size:medium;font-weight:normal;margin:0;padding:0}#res h3,#extrares h3{font-size:20px;line-height:1.3;}#cnt{clear:both}#res{margin:0 16px}ol li{list-style:none}.gl,#foot a,.nobr{white-space:nowrap}.sl,.r{font-weight:normal;margin:0}.r{font-size:medium}h4.r{font-size:small}.gic{position:relative;overflow:hidden;z-index:0}#rhs{display:block;margin-left:712px;padding-bottom:10px;min-width:268px}.mdm #rhs{margin-left:732px}.big #rhs{margin-left:792px}#rhs .scrt.rhsvw,#rhs table.rhsvw{border:0}#rhs .rhsvw{border:1px solid #ebebeb;padding-left:17px;padding-right:16px;position:relative;width:457px;-moz-box-sizing:border-box}#center_col .rhsl4,#center_col .rhsl5{display:none}#rhs.rhstc4 .rhsvw{width:369px}.rhstc4 .rhsg4{background:none !important;display:none !important}.rhstc5 .rhsl5,.rhstc5 .rhsl4,.rhstc4 .rhsl4{background:none !important;display:none !important}.nrgt{margin-left:22px;}.mslg .vsc{-moz-transition:opacity .2s ease;margin-top:2px;transition:opacity .2s ease;width:294px;border:1px solid transparent;border-radius:2px;border-radius:2px;padding:3px 0 3px 5px}.mslg>td{padding-right:6px;padding-top:4px}.vsc{display:inline-block;position:relative;width:100%}#res h3.r{display:block;overflow:hidden;text-overflow:ellipsis;-moz-text-overflow:ellipsis;white-space:nowrap;}em{font-weight:bold;font-style:normal}ol,ul,li{border:0;margin:0;padding:0}.g{margin-top:0;margin-bottom:28px}.tsw{width:595px}#cnt{min-width:833px;margin-left:0}.mw{max-width:1197px}.big .mw{max-width:1280px}.tsf-p{padding-left:180px;margin-right:46px;max-width:739px}.big .tsf-p{margin-right:322px;padding-left:180px}.col{float:left}#leftnavc,#center_col,#rhs{position:relative}#center_col{margin-left:138px;margin-right:264px;}.big #center_col{margin-left:138px;}#res{border:0;margin:0;}a:link,.q:active,.q:visited{cursor:pointer}.gl a,#tsf a,a.gl,a.fl,.bc a,#appbar a{text-decoration:none}.gl a:hover,#tsf a:hover,a.gl:hover,a.fl:hover,.bc a:hover{text-decoration:underline}#tads a,#tadsb a,#res a,#rhs a,#taw a,#brs a,.nsa,.fl,#botstuff a,#rhs .gl a{text-decoration:none}#foot{visibility:hidden}#fll a,#bfl a{color:#1a0dab;margin:0 12px;text-decoration:none}body{color:#222}.s{color:#4d5156}.s .st em,.st.s.std em{color:#5f6368}.s a:visited em{color:#609}.s a:active em{color:#dd4b39}#tsf{width:833px;}.big #tsf{width:1109px}.st{line-height:1.58;word-wrap:break-word}.sbc{padding:0 2px;min-width:30px}#rcnt{margin-top:0px;}#appbar,.rhscol{min-width:1261px}#appbar{background:#fff;-webkit-box-sizing:border-box;width:100%}#main{width:100%}#cnt #center_col,#cnt #foot{width:652px}#center_col{clear:both}#cnt #center_col,.mw #center_col{margin-left:180px}#rso{margin-top:6px}.mw #rhs{margin-left:892px;padding-right:8px}.th{border:1px solid #ebebeb}.ellip{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}</style><style>@-webkit-keyframes qs-timer {0%{}}.fp-f{bottom:0;height:auto;left:0;position:fixed !important;right:0;top:0;width:auto;z-index:127}.fp-h:not(.fp-nh):not(.goog-modalpopup-bg):not(.goog-modalpopup){display:none !important}.fp-zh.fp-h:not(.fp-nh):not(.goog-modalpopup-bg):not(.goog-modalpopup){display:block !important;height:0;overflow:hidden;transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0)}.fp-i .fp-c{display:block;min-height:100vh}li.fp-c{list-style:none}.fp-w{box-sizing:border-box;left:0;margin-left:auto;margin-right:auto;max-width:1217px;right:0}</style><script nonce="c+l/vHKNHR/yfOloi+dylw==">(function(){
+var b=[function(){google.tick&&google.tick("load","dcl")}];google.dclc=function(a){b.length?b.push(a):a()};function c(){for(var a;a=b.shift();)a()}window.addEventListener?(document.addEventListener("DOMContentLoaded",c,!1),window.addEventListener("load",c,!1)):window.attachEvent&&window.attachEvent("onload",c);}).call(this);(function(){
+window.rwt=function(){return!0};}).call(this);(function(){window.jsarwt=function(){return!1};}).call(this);</script><style>div#searchform{min-width:1261px;z-index:127}#gb{height:0;padding-left:16px;padding-right:16px}</style> <script nonce="c+l/vHKNHR/yfOloi+dylw==">;this.gbar_={CONFIG:[[[0,"www.gstatic.com","og.qtm.en_US.Y2mHzZ7HU2E.O","com","en","1",1,[4,2,".40.40.40.40.40.40.","","1300102,3700339,3700697","317576115","0"],null,"hN_zXpzsA4GWr7wP88i12AE",null,0,"og.qtm.-6ob9ysgt00dy.L.F4.O","AA2YrTuHxZSD4tXZcAmap_MDWGJq1F-pSg","AA2YrTuy2osiv-z56S2oNPKLgdL_hQ5WLQ","",2,1,200,"USA",null,null,"1","1",1],null,[1,0.1000000014901161,2,1],[1,0.001000000047497451,1],[0,0,0,null,"","","",""],[0,0,"",1,0,0,0,0,0,0,0,0,0,null,0,0,null,null,0,0,0,"","","","","","",null,0,0,0,0,0,null,null,null,"rgba(32,33,36,1)","rgba(255,255,255,1)",0,0,1,1,1],null,null,["1","gci_91f30755d6a6b787dcc2a4062e6e9824.js","googleapis.client:plusone:gapi.iframes","","en"],null,null,null,null,["m;/_/scs/abc-static/_/js/k=gapi.gapi.en.yyhByYeMTAc.O/am=AAY/d=1/ct=zgms/rs=AHpOoo-O470EQdZ-4tpWpppyTQmeOEUv-g/m=__features__","https://apis.google.com","","","","",null,1,"es_plusone_gc_20200601.0_p0","en",null,0,0],[0.009999999776482582,"com","1",[null,"","0",null,1,5184000,null,null,"",0,1,"",0,0,0,0,0,0,1,0,0,0,0,0,0,0],null,[["","","0",0,0,-1]],null,0,null,null,["5061451","google\\.(com|ru|ca|by|kz|com\\.mx|com\\.tr)$",1]],[1,1,null,40400,1,"USA","en","317576115.0",8,0.009999999776482582,0,0,null,null,0,0,"",null,null,null,"hN_zXpzsA4GWr7wP88i12AE",0],[[null,null,null,"https://www.gstatic.com/og/_/js/k=og.qtm.en_US.Y2mHzZ7HU2E.O/rt=j/m=qabr,q_d,qcwid,qmutsd,qapid/exm=qaaw,qadd,qaid,qein,qhaw,qhbr,qhch,qhga,qhid,qhin,qhpr/d=1/ed=1/rs=AA2YrTuHxZSD4tXZcAmap_MDWGJq1F-pSg"],[null,null,null,"https://www.gstatic.com/og/_/ss/k=og.qtm.-6ob9ysgt00dy.L.F4.O/m=qcwid/excm=qaaw,qadd,qaid,qein,qhaw,qhbr,qhch,qhga,qhid,qhin,qhpr/d=1/ed=1/ct=zgms/rs=AA2YrTuy2osiv-z56S2oNPKLgdL_hQ5WLQ"]],null,null,[""],[[[null,null,[null,null,null,"https://ogs.google.com/widget/app/so?gm2"],0,448,328,57,4,1,0,0,63,64,8000,"https://www.google.com/intl/en/about/products?tab=wh",67,1,69,null,1,70,"Can't seem to load the app launcher right now. Try again or go to the %1$sGoogle Products%2$s page.",3,1,0,74,0,null,null,null,null,null,null,1]],0,[null,null,null,"https://www.gstatic.com/og/_/js/k=og.qtm.en_US.Y2mHzZ7HU2E.O/rt=j/m=qdsh/d=1/ed=1/rs=AA2YrTuHxZSD4tXZcAmap_MDWGJq1F-pSg"],"1","1",1,0,null,"en",0]]],};this.gbar_=this.gbar_||{};(function(_){var window=this;
+try{
+/*
+
+ Copyright The Closure Library Authors.
+ SPDX-License-Identifier: Apache-2.0
+*/
+var aa,ba,ca,da,ea,ha,ja,ka,oa,pa,Ba,Ca,Ea;aa=function(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}};ba="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a};
+ca=function(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("a");};da=ca(this);ea=function(a,b){if(b)a:{var c=da;a=a.split(".");for(var d=0;d<a.length-1;d++){var e=a[d];if(!(e in c))break a;c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&ba(c,a,{configurable:!0,writable:!0,value:b})}};
+ea("Symbol",function(a){if(a)return a;var b=function(e,f){this.j=e;ba(this,"description",{configurable:!0,writable:!0,value:f})};b.prototype.toString=function(){return this.j};var c=0,d=function(e){if(this instanceof d)throw new TypeError("b");return new b("jscomp_symbol_"+(e||"")+"_"+c++,e)};return d});
+ea("Symbol.iterator",function(a){if(a)return a;a=Symbol("c");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;c<b.length;c++){var d=da[b[c]];"function"===typeof d&&"function"!=typeof d.prototype[a]&&ba(d.prototype,a,{configurable:!0,writable:!0,value:function(){return ha(aa(this))}})}return a});ha=function(a){a={next:a};a[Symbol.iterator]=function(){return this};return a};
+_.ia=function(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbol.iterator];return b?b.call(a):{next:aa(a)}};ja="function"==typeof Object.create?Object.create:function(a){var b=function(){};b.prototype=a;return new b};if("function"==typeof Object.setPrototypeOf)ka=Object.setPrototypeOf;else{var la;a:{var ma={Yg:!0},na={};try{na.__proto__=ma;la=na.Yg;break a}catch(a){}la=!1}ka=la?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError("d`"+a);return a}:null}oa=ka;
+_.n=function(a,b){a.prototype=ja(b.prototype);a.prototype.constructor=a;if(oa)oa(a,b);else for(var c in b)if("prototype"!=c)if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.P=b.prototype};pa=function(a,b,c){if(null==a)throw new TypeError("e`"+c);if(b instanceof RegExp)throw new TypeError("f`"+c);return a+""};
+ea("String.prototype.startsWith",function(a){return a?a:function(b,c){var d=pa(this,b,"startsWith"),e=d.length,f=b.length;c=Math.max(0,Math.min(c|0,d.length));for(var g=0;g<f&&c<e;)if(d[c++]!=b[g++])return!1;return g>=f}});ea("Number.MAX_SAFE_INTEGER",function(){return 9007199254740991});
+var qa=function(a,b){a instanceof String&&(a+="");var c=0,d={next:function(){if(c<a.length){var e=c++;return{value:b(e,a[e]),done:!1}}d.next=function(){return{done:!0,value:void 0}};return d.next()}};d[Symbol.iterator]=function(){return d};return d};ea("Array.prototype.keys",function(a){return a?a:function(){return qa(this,function(b){return b})}});ea("Array.prototype.values",function(a){return a?a:function(){return qa(this,function(b,c){return c})}});
+var ra=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};
+ea("WeakMap",function(a){function b(){}function c(l){var m=typeof l;return"object"===m&&null!==l||"function"===m}function d(l){if(!ra(l,f)){var m=new b;ba(l,f,{value:m})}}function e(l){var m=Object[l];m&&(Object[l]=function(r){if(r instanceof b)return r;Object.isExtensible(r)&&d(r);return m(r)})}if(function(){if(!a||!Object.seal)return!1;try{var l=Object.seal({}),m=Object.seal({}),r=new a([[l,2],[m,3]]);if(2!=r.get(l)||3!=r.get(m))return!1;r.delete(l);r.set(m,4);return!r.has(l)&&4==r.get(m)}catch(t){return!1}}())return a;
+var f="$jscomp_hidden_"+Math.random();e("freeze");e("preventExtensions");e("seal");var g=0,k=function(l){this.j=(g+=Math.random()+1).toString();if(l){l=_.ia(l);for(var m;!(m=l.next()).done;)m=m.value,this.